Changeset 8e6ecfe for storage_xml.c


Ignore:
Timestamp:
2016-03-25T18:07:53Z (8 years ago)
Author:
Dennis Kaarsemaker <dennis@…>
Branches:
master
Children:
a6005da
Parents:
446a23e
git-author:
Dennis Kaarsemaker <dennis@…> (23-02-16 18:41:34)
git-committer:
Dennis Kaarsemaker <dennis@…> (25-03-16 18:07:53)
Message:

Authentication: scaffolding for multiple authentication backends

Instead of always putting users passwords in XML files, allow site
admins to configure a different authentication method to integrate
authentication with other systems.

This doesn't add any authentication backends yet, merely the
scaffolding. Notably:

  • Password checking and loading/removing from storage has been decoupled. A new auth_check_pass function is used to check passwords. It does check against the configured storage first, but will handle the authentication backends as well. The XML storage merely signals that a user's password should be checked using an authentication backend.
  • If unknown-to-bitlbee users identify using an authentication backend, they are automatically registered.
  • If an authentication backend is used, that fact is stored in the XML file, the password is not. Passwords are also stored unencrypted in this case, as the password used to encrypt them can change underneath us.
  • configure and Makefile changes for the backend objects
File:
1 edited

Legend:

Unmodified
Added
Removed
  • storage_xml.c

    r446a23e r8e6ecfe  
    3434
    3535typedef enum {
    36         XML_PASS_CHECK_ONLY = -1,
    37         XML_PASS_UNKNOWN = 0,
    38         XML_PASS_WRONG,
    39         XML_PASS_OK
    40 } xml_pass_st;
     36        XML_PASS_CHECK = 0,
     37        XML_LOAD
     38} xml_action;
    4139
    4240/* To make it easier later when extending the format: */
     
    121119        if (!handle || !pass_b64 || !protocol || !prpl) {
    122120                return XT_ABORT;
    123         } else if ((pass_len = base64_decode(pass_b64, (unsigned char **) &pass_cr)) &&
    124                    arc_decode(pass_cr, pass_len, &password, xd->given_pass) >= 0) {
    125                 acc = account_add(xd->irc->b, prpl, handle, password);
    126                 if (server) {
    127                         set_setstr(&acc->set, "server", server);
    128                 }
    129                 if (autoconnect) {
    130                         set_setstr(&acc->set, "auto_connect", autoconnect);
    131                 }
    132                 if (tag) {
    133                         set_setstr(&acc->set, "tag", tag);
    134                 }
    135                 if (local) {
    136                         acc->flags |= ACC_FLAG_LOCAL;
    137                 }
    138                 if (locked && !g_strcasecmp(locked, "true")) {
    139                         acc->flags |= ACC_FLAG_LOCKED;
    140                 }
     121        }
     122
     123        base64_decode(pass_b64, (unsigned char **) &pass_cr);
     124        if (xd->irc->auth_backend) {
     125                password = g_strdup((char *)pass_cr);
    141126        } else {
    142                 g_free(pass_cr);
    143                 g_free(password);
    144                 return XT_ABORT;
     127                pass_len = arc_decode(pass_cr, pass_len, &password, xd->given_pass);
     128                if (pass_len < 0) {
     129                        g_free(pass_cr);
     130                        g_free(password);
     131                        return XT_ABORT;
     132                }
     133        }
     134
     135        acc = account_add(xd->irc->b, prpl, handle, password);
     136        if (server) {
     137                set_setstr(&acc->set, "server", server);
     138        }
     139        if (autoconnect) {
     140                set_setstr(&acc->set, "auto_connect", autoconnect);
     141        }
     142        if (tag) {
     143                set_setstr(&acc->set, "tag", tag);
     144        }
     145        if (local) {
     146                acc->flags |= ACC_FLAG_LOCAL;
     147        }
     148        if (locked && !g_strcasecmp(locked, "true")) {
     149                acc->flags |= ACC_FLAG_LOCKED;
    145150        }
    146151
     
    198203};
    199204
    200 static storage_status_t xml_load_real(irc_t *irc, const char *my_nick, const char *password, xml_pass_st action)
     205static storage_status_t xml_load_real(irc_t *irc, const char *my_nick, const char *password, xml_action action)
    201206{
    202207        struct xml_parsedata xd[1];
     
    240245        }
    241246
    242         {
     247        if (action == XML_PASS_CHECK) {
    243248                char *nick = xt_find_attr(node, "nick");
    244249                char *pass = xt_find_attr(node, "password");
    245 
    246                 if (!nick || !pass) {
     250                char *backend = xt_find_attr(node, "auth_backend");
     251
     252                if (!nick || !(pass || backend)) {
    247253                        goto error;
     254                }
     255
     256                if (backend) {
     257                        g_free(xd->irc->auth_backend);
     258                        xd->irc->auth_backend = g_strdup(backend);
     259                        ret = STORAGE_CHECK_BACKEND;
    248260                } else if ((st = md5_verify_password(xd->given_pass, pass)) != 0) {
    249261                        ret = STORAGE_INVALID_PASSWORD;
    250                         goto error;
    251                 }
    252         }
    253 
    254         if (action == XML_PASS_CHECK_ONLY) {
    255                 ret = STORAGE_OK;
    256                 goto error;
    257         }
    258 
    259         /* DO NOT call xt_handle() before verifying the password! */
     262                } else {
     263                        ret = STORAGE_OK;
     264                }
     265                goto error;
     266        }
     267
    260268        if (xt_handle(xp, NULL, 1) == XT_HANDLED) {
    261269                ret = STORAGE_OK;
     
    272280static storage_status_t xml_load(irc_t *irc, const char *password)
    273281{
    274         return xml_load_real(irc, irc->user->nick, password, XML_PASS_UNKNOWN);
    275 }
    276 
    277 static storage_status_t xml_check_pass(const char *my_nick, const char *password)
    278 {
    279         return xml_load_real(NULL, my_nick, password, XML_PASS_CHECK_ONLY);
     282        return xml_load_real(irc, irc->user->nick, password, XML_LOAD);
     283}
     284
     285static storage_status_t xml_check_pass(irc_t *irc, const char *my_nick, const char *password)
     286{
     287        return xml_load_real(irc, my_nick, password, XML_PASS_CHECK);
    280288}
    281289
     
    292300        struct xt_node *root, *cur;
    293301
    294         /* Generate a salted md5sum of the password. Use 5 bytes for the salt
    295            (to prevent dictionary lookups of passwords) to end up with a 21-
    296            byte password hash, more convenient for base64 encoding. */
    297         random_bytes(pass_md5 + 16, 5);
    298         md5_init(&md5_state);
    299         md5_append(&md5_state, (md5_byte_t *) irc->password, strlen(irc->password));
    300         md5_append(&md5_state, pass_md5 + 16, 5);   /* Add the salt. */
    301         md5_finish(&md5_state, pass_md5);
    302         /* Save the hash in base64-encoded form. */
    303         pass_buf = base64_encode(pass_md5, 21);
    304 
    305302        root = cur = xt_new_node("user", NULL, NULL);
     303        if (irc->auth_backend) {
     304                xt_add_attr(cur, "auth_backend", irc->auth_backend);
     305        } else {
     306                /* Generate a salted md5sum of the password. Use 5 bytes for the salt
     307                   (to prevent dictionary lookups of passwords) to end up with a 21-
     308                   byte password hash, more convenient for base64 encoding. */
     309                random_bytes(pass_md5 + 16, 5);
     310                md5_init(&md5_state);
     311                md5_append(&md5_state, (md5_byte_t *) irc->password, strlen(irc->password));
     312                md5_append(&md5_state, pass_md5 + 16, 5);   /* Add the salt. */
     313                md5_finish(&md5_state, pass_md5);
     314                /* Save the hash in base64-encoded form. */
     315                pass_buf = base64_encode(pass_md5, 21);
     316                xt_add_attr(cur, "password", pass_buf);
     317                g_free(pass_buf);
     318        }
     319
    306320        xt_add_attr(cur, "nick", irc->user->nick);
    307         xt_add_attr(cur, "password", pass_buf);
    308321        xt_add_attr(cur, "version", XML_FORMAT_VERSION);
    309 
    310         g_free(pass_buf);
    311322
    312323        xml_generate_settings(cur, &irc->b->set);
     
    319330                int pass_len;
    320331
    321                 pass_len = arc_encode(acc->pass, strlen(acc->pass), (unsigned char **) &pass_cr, irc->password, 12);
    322                 pass_b64 = base64_encode(pass_cr, pass_len);
    323                 g_free(pass_cr);
     332                if(irc->auth_backend) {
     333                        /* If we don't "own" the password, it may change without us
     334                         * knowing, so we cannot encrypt the data, as we then may not be
     335                         * able to decrypt it */
     336                        pass_b64 = base64_encode((unsigned char *)acc->pass, strlen(acc->pass));
     337                } else {
     338                        pass_len = arc_encode(acc->pass, strlen(acc->pass), (unsigned char **) &pass_cr, irc->password, 12);
     339                        pass_b64 = base64_encode(pass_cr, pass_len);
     340                        g_free(pass_cr);
     341                }
    324342
    325343                cur = xt_new_node("account", NULL, NULL);
     
    440458
    441459
    442 static storage_status_t xml_remove(const char *nick, const char *password)
     460static storage_status_t xml_remove(const char *nick)
    443461{
    444462        char s[512], *lc;
    445         storage_status_t status;
    446 
    447         status = xml_check_pass(nick, password);
    448         if (status != STORAGE_OK) {
    449                 return status;
    450         }
    451463
    452464        lc = g_strdup(nick);
Note: See TracChangeset for help on using the changeset viewer.