diff options
Diffstat (limited to 'storage_xml.c')
| -rw-r--r-- | storage_xml.c | 136 | 
1 files changed, 74 insertions, 62 deletions
| diff --git a/storage_xml.c b/storage_xml.c index dbdd151d..7e8555ef 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -33,11 +33,9 @@  #include <glib/gstdio.h>  typedef enum { -	XML_PASS_CHECK_ONLY = -1, -	XML_PASS_UNKNOWN = 0, -	XML_PASS_WRONG, -	XML_PASS_OK -} xml_pass_st; +	XML_PASS_CHECK = 0, +	XML_LOAD +} xml_action;  /* To make it easier later when extending the format: */  #define XML_FORMAT_VERSION "1" @@ -120,28 +118,35 @@ static xt_status handle_account(struct xt_node *node, gpointer data)  	if (!handle || !pass_b64 || !protocol || !prpl) {  		return XT_ABORT; -	} else if ((pass_len = base64_decode(pass_b64, (unsigned char **) &pass_cr)) && -	           arc_decode(pass_cr, pass_len, &password, xd->given_pass) >= 0) { -		acc = account_add(xd->irc->b, prpl, handle, password); -		if (server) { -			set_setstr(&acc->set, "server", server); -		} -		if (autoconnect) { -			set_setstr(&acc->set, "auto_connect", autoconnect); -		} -		if (tag) { -			set_setstr(&acc->set, "tag", tag); -		} -		if (local) { -			acc->flags |= ACC_FLAG_LOCAL; -		} -		if (locked && !g_strcasecmp(locked, "true")) { -			acc->flags |= ACC_FLAG_LOCKED; -		} +	} + +	base64_decode(pass_b64, (unsigned char **) &pass_cr); +	if (xd->irc->auth_backend) { +		password = g_strdup((char *)pass_cr);  	} else { -		g_free(pass_cr); -		g_free(password); -		return XT_ABORT; +		pass_len = arc_decode(pass_cr, pass_len, &password, xd->given_pass); +		if (pass_len < 0) { +			g_free(pass_cr); +			g_free(password); +			return XT_ABORT; +		} +	} + +	acc = account_add(xd->irc->b, prpl, handle, password); +	if (server) { +		set_setstr(&acc->set, "server", server); +	} +	if (autoconnect) { +		set_setstr(&acc->set, "auto_connect", autoconnect); +	} +	if (tag) { +		set_setstr(&acc->set, "tag", tag); +	} +	if (local) { +		acc->flags |= ACC_FLAG_LOCAL; +	} +	if (locked && !g_strcasecmp(locked, "true")) { +		acc->flags |= ACC_FLAG_LOCKED;  	}  	g_free(pass_cr); @@ -197,7 +202,7 @@ static const struct xt_handler_entry handlers[] = {  	{ NULL,      NULL,   NULL, },  }; -static storage_status_t xml_load_real(irc_t *irc, const char *my_nick, const char *password, xml_pass_st action) +static storage_status_t xml_load_real(irc_t *irc, const char *my_nick, const char *password, xml_action action)  {  	struct xml_parsedata xd[1];  	char *fn, buf[2048]; @@ -239,24 +244,27 @@ static storage_status_t xml_load_real(irc_t *irc, const char *my_nick, const cha  		goto error;  	} -	{ +	if (action == XML_PASS_CHECK) {  		char *nick = xt_find_attr(node, "nick");  		char *pass = xt_find_attr(node, "password"); +		char *backend = xt_find_attr(node, "auth_backend"); -		if (!nick || !pass) { +		if (!nick || !(pass || backend)) {  			goto error; +		} + +		if (backend) { +			g_free(xd->irc->auth_backend); +			xd->irc->auth_backend = g_strdup(backend); +			ret = STORAGE_CHECK_BACKEND;  		} else if ((st = md5_verify_password(xd->given_pass, pass)) != 0) {  			ret = STORAGE_INVALID_PASSWORD; -			goto error; +		} else { +			ret = STORAGE_OK;  		} -	} - -	if (action == XML_PASS_CHECK_ONLY) { -		ret = STORAGE_OK;  		goto error;  	} -	/* DO NOT call xt_handle() before verifying the password! */  	if (xt_handle(xp, NULL, 1) == XT_HANDLED) {  		ret = STORAGE_OK;  	} @@ -271,12 +279,12 @@ error:  static storage_status_t xml_load(irc_t *irc, const char *password)  { -	return xml_load_real(irc, irc->user->nick, password, XML_PASS_UNKNOWN); +	return xml_load_real(irc, irc->user->nick, password, XML_LOAD);  } -static storage_status_t xml_check_pass(const char *my_nick, const char *password) +static storage_status_t xml_check_pass(irc_t *irc, const char *my_nick, const char *password)  { -	return xml_load_real(NULL, my_nick, password, XML_PASS_CHECK_ONLY); +	return xml_load_real(irc, my_nick, password, XML_PASS_CHECK);  } @@ -291,24 +299,27 @@ struct xt_node *xml_generate(irc_t *irc)  	GSList *l;  	struct xt_node *root, *cur; -	/* Generate a salted md5sum of the password. Use 5 bytes for the salt -	   (to prevent dictionary lookups of passwords) to end up with a 21- -	   byte password hash, more convenient for base64 encoding. */ -	random_bytes(pass_md5 + 16, 5); -	md5_init(&md5_state); -	md5_append(&md5_state, (md5_byte_t *) irc->password, strlen(irc->password)); -	md5_append(&md5_state, pass_md5 + 16, 5);   /* Add the salt. */ -	md5_finish(&md5_state, pass_md5); -	/* Save the hash in base64-encoded form. */ -	pass_buf = base64_encode(pass_md5, 21); -  	root = cur = xt_new_node("user", NULL, NULL); +	if (irc->auth_backend) { +		xt_add_attr(cur, "auth_backend", irc->auth_backend); +	} else { +		/* Generate a salted md5sum of the password. Use 5 bytes for the salt +		   (to prevent dictionary lookups of passwords) to end up with a 21- +		   byte password hash, more convenient for base64 encoding. */ +		random_bytes(pass_md5 + 16, 5); +		md5_init(&md5_state); +		md5_append(&md5_state, (md5_byte_t *) irc->password, strlen(irc->password)); +		md5_append(&md5_state, pass_md5 + 16, 5);   /* Add the salt. */ +		md5_finish(&md5_state, pass_md5); +		/* Save the hash in base64-encoded form. */ +		pass_buf = base64_encode(pass_md5, 21); +		xt_add_attr(cur, "password", pass_buf); +		g_free(pass_buf); +	} +  	xt_add_attr(cur, "nick", irc->user->nick); -	xt_add_attr(cur, "password", pass_buf);  	xt_add_attr(cur, "version", XML_FORMAT_VERSION); -	g_free(pass_buf); -  	xml_generate_settings(cur, &irc->b->set);  	for (acc = irc->b->accounts; acc; acc = acc->next) { @@ -318,9 +329,16 @@ struct xt_node *xml_generate(irc_t *irc)  		char *pass_b64;  		int pass_len; -		pass_len = arc_encode(acc->pass, strlen(acc->pass), (unsigned char **) &pass_cr, irc->password, 12); -		pass_b64 = base64_encode(pass_cr, pass_len); -		g_free(pass_cr); +		if(irc->auth_backend) { +			/* If we don't "own" the password, it may change without us +			 * knowing, so we cannot encrypt the data, as we then may not be +			 * able to decrypt it */ +			pass_b64 = base64_encode((unsigned char *)acc->pass, strlen(acc->pass)); +		} else { +			pass_len = arc_encode(acc->pass, strlen(acc->pass), (unsigned char **) &pass_cr, irc->password, 12); +			pass_b64 = base64_encode(pass_cr, pass_len); +			g_free(pass_cr); +		}  		cur = xt_new_node("account", NULL, NULL);  		xt_add_attr(cur, "protocol", acc->prpl->name); @@ -439,15 +457,9 @@ finish:  } -static storage_status_t xml_remove(const char *nick, const char *password) +static storage_status_t xml_remove(const char *nick)  {  	char s[512], *lc; -	storage_status_t status; - -	status = xml_check_pass(nick, password); -	if (status != STORAGE_OK) { -		return status; -	}  	lc = g_strdup(nick);  	nick_lc(NULL, lc); | 
