Changeset 8e6ecfe
- Timestamp:
- 2016-03-25T18:07:53Z (9 years ago)
- 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)
- Files:
-
- 2 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
Makefile
r446a23e r8e6ecfe 10 10 11 11 # Program variables 12 objects = bitlbee.o dcc.o help.o ipc.o irc.o irc_im.o irc_cap.o irc_channel.o irc_commands.o irc_send.o irc_user.o irc_util.o nick.o $(OTR_BI) query.o root_commands.o set.o storage.o $(STORAGE_OBJS) unix.o conf.o log.o12 objects = bitlbee.o dcc.o help.o ipc.o irc.o irc_im.o irc_cap.o irc_channel.o irc_commands.o irc_send.o irc_user.o irc_util.o nick.o $(OTR_BI) query.o root_commands.o set.o storage.o $(STORAGE_OBJS) auth.o $(AUTH_OBJS) unix.o conf.o log.o 13 13 headers = $(wildcard $(_SRCDIR_)*.h $(_SRCDIR_)lib/*.h $(_SRCDIR_)protocols/*.h) 14 14 subdirs = lib protocols -
bitlbee.conf
r446a23e r8e6ecfe 51 51 ## 52 52 # AuthMode = Open 53 54 ## AuthBackend 55 ## 56 ## By default, the authentication data for a user is stored in the storage 57 ## backend. If you want to authenticate against another authentication system 58 ## (e.g. ldap), you can specify that here. 59 ## 60 ## Beware that this disables password changes and causes passwords for the 61 ## accounts people create to be stored in plain text instead of encrypted with 62 ## their bitlbee password. 63 # 64 # AuthBackend = storage 65 # 53 66 54 67 ## AuthPassword -
bitlbee.h
r446a23e r8e6ecfe 133 133 #include "irc.h" 134 134 #include "storage.h" 135 #include "auth.h" 135 136 #include "set.h" 136 137 #include "nogaim.h" … … 154 155 conf_t *conf; 155 156 GList *storage; /* The first backend in the list will be used for saving */ 157 GList *auth; /* Authentication backends */ 156 158 char *helpfile; 157 159 int restart; -
conf.c
r446a23e r8e6ecfe 55 55 conf->runmode = RUNMODE_INETD; 56 56 conf->authmode = AUTHMODE_OPEN; 57 conf->auth_backend = NULL; 57 58 conf->auth_pass = NULL; 58 59 conf->oper_pass = NULL; … … 241 242 conf->authmode = AUTHMODE_OPEN; 242 243 } 244 } else if (g_strcasecmp(ini->key, "authbackend") == 0) { 245 if (g_strcasecmp(ini->value, "storage") == 0) { 246 conf->auth_backend = NULL; 247 } else { 248 fprintf(stderr, "Invalid %s value: %s\n", ini->key, ini->value); 249 return 0; 250 } 243 251 } else if (g_strcasecmp(ini->key, "authpassword") == 0) { 244 252 g_free(conf->auth_pass); -
conf.h
r446a23e r8e6ecfe 37 37 runmode_t runmode; 38 38 authmode_t authmode; 39 char *auth_backend; 39 40 char *auth_pass; 40 41 char *oper_pass; -
configure
r446a23e r8e6ecfe 628 628 done 629 629 echo "STORAGE_OBJS="$STORAGE_OBJS >> Makefile.settings 630 631 authobjs= 632 authlibs= 633 echo AUTH_OBJS=$authobjs >> Makefile.settings 634 echo EFLAGS+=$authlibs >> Makefile.settings 630 635 631 636 if [ "$strip" = 0 ]; then -
irc.h
r446a23e r8e6ecfe 92 92 logging in, this may contain a password we should 93 93 send to identify after USER/NICK are received. */ 94 char *auth_backend; 94 95 95 96 char umode[8]; -
irc_commands.c
r446a23e r8e6ecfe 97 97 /* just check the password here to be able to reply with useful numerics 98 98 * the actual identification will be handled later */ 99 status = storage_check_pass(user, pass);99 status = auth_check_pass(irc, user, pass); 100 100 101 101 if (status == STORAGE_OK) { -
root_commands.c
r446a23e r8e6ecfe 143 143 } 144 144 145 if (load) { 145 status = auth_check_pass(irc, irc->user->nick, password); 146 if (load && (status == STORAGE_OK)) { 146 147 status = storage_load(irc, password); 147 } else {148 status = storage_check_pass(irc->user->nick, password);149 148 } 150 149 … … 159 158 irc_rootmsg(irc, "Password accepted%s", 160 159 load ? ", settings and accounts loaded" : ""); 161 irc_setpass(irc, password);162 160 irc->status |= USTATUS_IDENTIFIED; 163 161 irc_umode_set(irc, "+R", 1); … … 268 266 storage_status_t status; 269 267 270 status = storage_remove(irc->user->nick, cmd[1]); 268 status = auth_check_pass(irc, irc->user->nick, cmd[1]); 269 if (status == STORAGE_OK) { 270 status = storage_remove(irc->user->nick); 271 } 272 271 273 switch (status) { 272 274 case STORAGE_NO_SUCH_USER: -
storage.c
r446a23e r8e6ecfe 87 87 } 88 88 89 storage_status_t storage_check_pass( const char *nick, const char *password)89 storage_status_t storage_check_pass(irc_t *irc, const char *nick, const char *password) 90 90 { 91 91 GList *gl; … … 97 97 storage_status_t status; 98 98 99 status = st->check_pass( nick, password);99 status = st->check_pass(irc, nick, password); 100 100 if (status != STORAGE_NO_SUCH_USER) { 101 101 return status; … … 171 171 } 172 172 173 storage_status_t storage_remove(const char *nick , const char *password)173 storage_status_t storage_remove(const char *nick) 174 174 { 175 175 GList *gl; … … 185 185 storage_status_t status; 186 186 187 status = st->remove(nick , password);187 status = st->remove(nick); 188 188 ok |= status == STORAGE_OK; 189 189 if (status != STORAGE_NO_SUCH_USER && status != STORAGE_OK) { -
storage.h
r446a23e r8e6ecfe 31 31 STORAGE_NO_SUCH_USER, 32 32 STORAGE_INVALID_PASSWORD, 33 STORAGE_CHECK_BACKEND, 33 34 STORAGE_ALREADY_EXISTS, 34 35 STORAGE_OTHER_ERROR /* Error that isn't caused by user input, such as … … 43 44 void (*init)(void); 44 45 45 storage_status_t (*check_pass)( const char *nick, const char *password);46 storage_status_t (*check_pass)(irc_t *irc, const char *nick, const char *password); 46 47 47 48 storage_status_t (*load)(irc_t *irc, const char *password); 48 49 storage_status_t (*save)(irc_t *irc, int overwrite); 49 storage_status_t (*remove)(const char *nick , const char *password);50 storage_status_t (*remove)(const char *nick); 50 51 51 52 /* May be NULL if not supported by backend */ … … 53 54 } storage_t; 54 55 55 storage_status_t storage_check_pass( const char *nick, const char *password);56 storage_status_t storage_check_pass(irc_t *irc, const char *nick, const char *password); 56 57 57 58 storage_status_t storage_load(irc_t * irc, const char *password); 58 59 storage_status_t storage_save(irc_t *irc, char *password, int overwrite); 59 storage_status_t storage_remove(const char *nick , const char *password);60 storage_status_t storage_remove(const char *nick); 60 61 61 62 void register_storage_backend(storage_t *); -
storage_xml.c
r446a23e r8e6ecfe 34 34 35 35 typedef 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; 41 39 42 40 /* To make it easier later when extending the format: */ … … 121 119 if (!handle || !pass_b64 || !protocol || !prpl) { 122 120 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); 141 126 } 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; 145 150 } 146 151 … … 198 203 }; 199 204 200 static storage_status_t xml_load_real(irc_t *irc, const char *my_nick, const char *password, xml_ pass_staction)205 static storage_status_t xml_load_real(irc_t *irc, const char *my_nick, const char *password, xml_action action) 201 206 { 202 207 struct xml_parsedata xd[1]; … … 240 245 } 241 246 242 {247 if (action == XML_PASS_CHECK) { 243 248 char *nick = xt_find_attr(node, "nick"); 244 249 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)) { 247 253 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; 248 260 } else if ((st = md5_verify_password(xd->given_pass, pass)) != 0) { 249 261 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 260 268 if (xt_handle(xp, NULL, 1) == XT_HANDLED) { 261 269 ret = STORAGE_OK; … … 272 280 static storage_status_t xml_load(irc_t *irc, const char *password) 273 281 { 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 285 static 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); 280 288 } 281 289 … … 292 300 struct xt_node *root, *cur; 293 301 294 /* Generate a salted md5sum of the password. Use 5 bytes for the salt295 (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 305 302 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 306 320 xt_add_attr(cur, "nick", irc->user->nick); 307 xt_add_attr(cur, "password", pass_buf);308 321 xt_add_attr(cur, "version", XML_FORMAT_VERSION); 309 310 g_free(pass_buf);311 322 312 323 xml_generate_settings(cur, &irc->b->set); … … 319 330 int pass_len; 320 331 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 } 324 342 325 343 cur = xt_new_node("account", NULL, NULL); … … 440 458 441 459 442 static storage_status_t xml_remove(const char *nick , const char *password)460 static storage_status_t xml_remove(const char *nick) 443 461 { 444 462 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 }451 463 452 464 lc = g_strdup(nick); -
tests/Makefile
r446a23e r8e6ecfe 15 15 distclean: clean 16 16 17 main_objs = bitlbee.o conf.o dcc.o help.o ipc.o irc.o irc_cap.o irc_channel.o irc_commands.o irc_im.o irc_send.o irc_user.o irc_util.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o 17 main_objs = bitlbee.o conf.o dcc.o help.o ipc.o irc.o irc_cap.o irc_channel.o irc_commands.o irc_im.o irc_send.o irc_user.o irc_util.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o auth.o 18 18 19 19 test_objs = check.o check_util.o check_nick.o check_md5.o check_arc.o check_irc.o check_help.o check_user.o check_set.o check_jabber_sasl.o check_jabber_util.o -
unix.c
r446a23e r8e6ecfe 104 104 } 105 105 106 global.auth = auth_init(global.conf->auth_backend); 107 if (global.conf->auth_backend && global.auth == NULL) { 108 log_message(LOGLVL_ERROR, "Unable to load authentication backend '%s'", global.conf->auth_backend); 109 return(1); 110 } 111 106 112 if (global.conf->runmode == RUNMODE_INETD) { 107 113 log_link(LOGLVL_ERROR, LOGOUTPUT_IRC);
Note: See TracChangeset
for help on using the changeset viewer.