static int account_mgmt(int lld_no, struct mgmt_task *mtask) { struct tgtadm_req *req = &mtask->req; struct tgtadm_rsp *rsp = &mtask->rsp; int err = TGTADM_UNSUPPORTED_OPERATION; char *user, *password; switch (req->op) { case OP_NEW: case OP_DELETE: case OP_BIND: case OP_UNBIND: user = strstr(mtask->buf, "user="******"password="); err = account_add(user, password); } else { if (req->op == OP_DELETE) { err = account_del(user); } else err = account_ctl(req->tid, req->ac_dir, user, req->op == OP_BIND); } break; case OP_SHOW: retry: err = account_show(mtask->buf, mtask->bsize); if (err == mtask->bsize) { char *p; mtask->bsize <<= 1; p = realloc(mtask->buf, mtask->bsize); if (p) { mtask->buf = p; goto retry; } else err = TGTADM_NOMEM; } break; default: break; } out: if (req->op == OP_SHOW) set_show_results(rsp, &err); else { rsp->err = err; rsp->len = sizeof(*rsp); } return err; }
static xt_status handle_account( struct xt_node *node, gpointer data ) { struct xml_parsedata *xd = data; char *protocol, *handle, *server, *password = NULL, *autoconnect, *tag; char *pass_b64 = NULL; unsigned char *pass_cr = NULL; int pass_len; struct prpl *prpl = NULL; account_t *acc; struct xt_node *c; handle = xt_find_attr( node, "handle" ); pass_b64 = xt_find_attr( node, "password" ); server = xt_find_attr( node, "server" ); autoconnect = xt_find_attr( node, "autoconnect" ); tag = xt_find_attr( node, "tag" ); protocol = xt_find_attr( node, "protocol" ); if( protocol ) prpl = find_protocol( protocol ); 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 ); } else return XT_ABORT; g_free( pass_cr ); g_free( password ); handle_settings( node, &acc->set ); for( c = node->children; ( c = xt_find_node( c, "buddy" ) ); c = c->next ) { char *handle, *nick; handle = xt_find_attr( c, "handle" ); nick = xt_find_attr( c, "nick" ); if( handle && nick ) nick_set_raw( acc, handle, nick ); else return XT_ABORT; } return XT_HANDLED; }
static tgtadm_err account_mgmt(int lld_no, struct mgmt_task *mtask) { struct tgtadm_req *req = &mtask->req; char *user, *password; tgtadm_err adm_err = TGTADM_UNSUPPORTED_OPERATION; switch (req->op) { case OP_NEW: case OP_DELETE: case OP_BIND: case OP_UNBIND: user = strstr(mtask->req_buf, "user="******"password="); adm_err = account_add(user, password); } else { if (req->op == OP_DELETE) { adm_err = account_del(user); } else adm_err = account_ctl(req->tid, req->ac_dir, user, req->op == OP_BIND); } break; case OP_SHOW: concat_buf_init(&mtask->rsp_concat); adm_err = account_show(&mtask->rsp_concat); concat_buf_finish(&mtask->rsp_concat); break; default: break; } return adm_err; }
static void cmd_account(irc_t *irc, char **cmd) { account_t *a; int len; if (global.conf->authmode == AUTHMODE_REGISTERED && !(irc->status & USTATUS_IDENTIFIED)) { irc_rootmsg(irc, "This server only accepts registered users"); return; } len = strlen(cmd[1]); if (len >= 1 && g_strncasecmp(cmd[1], "add", len) == 0) { struct prpl *prpl; MIN_ARGS(3); if (!global.conf->allow_account_add) { irc_rootmsg(irc, "This server does not allow adding new accounts"); return; } if (cmd[4] == NULL) { for (a = irc->b->accounts; a; a = a->next) { if (strcmp(a->pass, PASSWORD_PENDING) == 0) { irc_rootmsg(irc, "Enter password for account %s " "first (use /OPER)", a->tag); return; } } irc->status |= OPER_HACK_ACCOUNT_PASSWORD; } prpl = find_protocol(cmd[2]); if (prpl == NULL) { if (is_protocol_disabled(cmd[2])) { irc_rootmsg(irc, "Protocol disabled in global config"); } else { irc_rootmsg(irc, "Unknown protocol"); } return; } for (a = irc->b->accounts; a; a = a->next) { if (a->prpl == prpl && prpl->handle_cmp(a->user, cmd[3]) == 0) { irc_rootmsg(irc, "Warning: You already have an account with " "protocol `%s' and username `%s'. Are you accidentally " "trying to add it twice?", prpl->name, cmd[3]); } } a = account_add(irc->b, prpl, cmd[3], cmd[4] ? cmd[4] : PASSWORD_PENDING); if (cmd[5]) { irc_rootmsg(irc, "Warning: Passing a servername/other flags to `account add' " "is now deprecated. Use `account set' instead."); set_setstr(&a->set, "server", cmd[5]); } irc_rootmsg(irc, "Account successfully added with tag %s", a->tag); if (cmd[4] == NULL) { set_t *oauth = set_find(&a->set, "oauth"); if (oauth && bool2int(set_value(oauth))) { *a->pass = '******'; irc_rootmsg(irc, "No need to enter a password for this " "account since it's using OAuth"); } else { irc_rootmsg(irc, "You can now use the /OPER command to " "enter the password"); if (oauth) { irc_rootmsg(irc, "Alternatively, enable OAuth if " "the account supports it: account %s " "set oauth on", a->tag); } } } return; } else if (len >= 1 && g_strncasecmp(cmd[1], "list", len) == 0) { int i = 0; if (strchr(irc->umode, 'b')) { irc_rootmsg(irc, "Account list:"); } for (a = irc->b->accounts; a; a = a->next) { char *con; if (a->ic && (a->ic->flags & OPT_LOGGED_IN)) { con = " (connected)"; } else if (a->ic) { con = " (connecting)"; } else if (a->reconnect) { con = " (awaiting reconnect)"; } else { con = ""; } irc_rootmsg(irc, "%2d (%s): %s, %s%s", i, a->tag, a->prpl->name, a->user, con); i++; } irc_rootmsg(irc, "End of account list"); return; } else if (cmd[2]) { /* Try the following two only if cmd[2] == NULL */ } else if (len >= 2 && g_strncasecmp(cmd[1], "on", len) == 0) { if (irc->b->accounts) { irc_rootmsg(irc, "Trying to get all accounts connected..."); for (a = irc->b->accounts; a; a = a->next) { if (!a->ic && a->auto_connect) { if (strcmp(a->pass, PASSWORD_PENDING) == 0) { irc_rootmsg(irc, "Enter password for account %s " "first (use /OPER)", a->tag); } else { account_on(irc->b, a); } } } } else { irc_rootmsg(irc, "No accounts known. Use `account add' to add one."); } return; } else if (len >= 2 && g_strncasecmp(cmd[1], "off", len) == 0) { irc_rootmsg(irc, "Deactivating all active (re)connections..."); for (a = irc->b->accounts; a; a = a->next) { if (a->ic) { account_off(irc->b, a); } else if (a->reconnect) { cancel_auto_reconnect(a); } } return; } MIN_ARGS(2); len = strlen(cmd[2]); /* At least right now, don't accept on/off/set/del as account IDs even if they're a proper match, since people not familiar with the new syntax yet may get a confusing/nasty surprise. */ if (g_strcasecmp(cmd[1], "on") == 0 || g_strcasecmp(cmd[1], "off") == 0 || g_strcasecmp(cmd[1], "set") == 0 || g_strcasecmp(cmd[1], "del") == 0 || (a = account_get(irc->b, cmd[1])) == NULL) { irc_rootmsg(irc, "Could not find account `%s'.", cmd[1]); return; } if (len >= 1 && g_strncasecmp(cmd[2], "del", len) == 0) { if (a->flags & ACC_FLAG_LOCKED) { irc_rootmsg(irc, "Account is locked, can't delete"); } else if (a->ic) { irc_rootmsg(irc, "Account is still logged in, can't delete"); } else { account_del(irc->b, a); irc_rootmsg(irc, "Account deleted"); } } else if (len >= 2 && g_strncasecmp(cmd[2], "on", len) == 0) { if (a->ic) { irc_rootmsg(irc, "Account already online"); } else if (strcmp(a->pass, PASSWORD_PENDING) == 0) { irc_rootmsg(irc, "Enter password for account %s " "first (use /OPER)", a->tag); } else { account_on(irc->b, a); } } else if (len >= 2 && g_strncasecmp(cmd[2], "off", len) == 0) { if (a->ic) { account_off(irc->b, a); } else if (a->reconnect) { cancel_auto_reconnect(a); irc_rootmsg(irc, "Reconnect cancelled"); } else { irc_rootmsg(irc, "Account already offline"); } } else if (len >= 1 && g_strncasecmp(cmd[2], "set", len) == 0) { cmd_set_real(irc, cmd + 2, &a->set, cmd_account_set_checkflags); } else { irc_rootmsg(irc, "Unknown command: %s [...] %s. Please use \x02help commands\x02 to get a list of available commands.", "account", cmd[2]); } }
static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_name, const gchar **attr_names, const gchar **attr_values, gpointer data, GError **error ) { struct xml_parsedata *xd = data; irc_t *irc = xd->irc; if( xd->unknown_tag > 0 ) { xd->unknown_tag ++; } else if( g_strcasecmp( element_name, "user" ) == 0 ) { char *nick = xml_attr( attr_names, attr_values, "nick" ); char *pass = xml_attr( attr_names, attr_values, "password" ); int st; if( !nick || !pass ) { g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Missing attributes for %s element", element_name ); } else if( ( st = md5_verify_password( xd->given_pass, pass ) ) == -1 ) { xd->pass_st = XML_PASS_WRONG; g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Error while decoding password attribute" ); } else if( st == 0 ) { if( xd->pass_st != XML_PASS_CHECK_ONLY ) xd->pass_st = XML_PASS_OK; } else { xd->pass_st = XML_PASS_WRONG; g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Password mismatch" ); } } else if( xd->pass_st < XML_PASS_OK ) { /* Let's not parse anything else if we only have to check the password. */ } else if( g_strcasecmp( element_name, "account" ) == 0 ) { char *protocol, *handle, *server, *password = NULL, *autoconnect, *tag; char *pass_b64 = NULL; unsigned char *pass_cr = NULL; int pass_len; struct prpl *prpl = NULL; handle = xml_attr( attr_names, attr_values, "handle" ); pass_b64 = xml_attr( attr_names, attr_values, "password" ); server = xml_attr( attr_names, attr_values, "server" ); autoconnect = xml_attr( attr_names, attr_values, "autoconnect" ); tag = xml_attr( attr_names, attr_values, "tag" ); protocol = xml_attr( attr_names, attr_values, "protocol" ); if( protocol ) prpl = find_protocol( protocol ); if( !handle || !pass_b64 || !protocol ) g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Missing attributes for %s element", element_name ); else if( !prpl ) g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Unknown protocol: %s", protocol ); else if( ( pass_len = base64_decode( pass_b64, (unsigned char**) &pass_cr ) ) && arc_decode( pass_cr, pass_len, &password, xd->given_pass ) >= 0 ) { xd->current_account = account_add( irc->b, prpl, handle, password ); if( server ) set_setstr( &xd->current_account->set, "server", server ); if( autoconnect ) set_setstr( &xd->current_account->set, "auto_connect", autoconnect ); if( tag ) set_setstr( &xd->current_account->set, "tag", tag ); } else { /* Actually the _decode functions don't even return error codes, but maybe they will later... */ g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Error while decrypting account password" ); } g_free( pass_cr ); g_free( password ); } else if( g_strcasecmp( element_name, "setting" ) == 0 ) { char *setting; if( xd->current_setting ) { g_free( xd->current_setting ); xd->current_setting = NULL; } if( ( setting = xml_attr( attr_names, attr_values, "name" ) ) ) { if( xd->current_channel != NULL ) xd->current_set_head = &xd->current_channel->set; else if( xd->current_account != NULL ) xd->current_set_head = &xd->current_account->set; else xd->current_set_head = &xd->irc->b->set; xd->current_setting = g_strdup( setting ); } else g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Missing attributes for %s element", element_name ); } else if( g_strcasecmp( element_name, "buddy" ) == 0 ) { char *handle, *nick; handle = xml_attr( attr_names, attr_values, "handle" ); nick = xml_attr( attr_names, attr_values, "nick" ); if( xd->current_account && handle && nick ) { nick_set_raw( xd->current_account, handle, nick ); } else { g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Missing attributes for %s element", element_name ); } } else if( g_strcasecmp( element_name, "channel" ) == 0 ) { char *name, *type; name = xml_attr( attr_names, attr_values, "name" ); type = xml_attr( attr_names, attr_values, "type" ); if( !name || !type ) { g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Missing attributes for %s element", element_name ); return; } /* The channel may exist already, for example if it's &bitlbee. Also, it's possible that the user just reconnected and the IRC client already rejoined all channels it was in. They should still get the right settings. */ if( ( xd->current_channel = irc_channel_by_name( irc, name ) ) || ( xd->current_channel = irc_channel_new( irc, name ) ) ) set_setstr(&xd->current_channel->set, "type", type ); } /* Backward compatibility: Keep this around for a while for people switching from BitlBee 1.2.4+. */ else if( g_strcasecmp( element_name, "chat" ) == 0 ) { char *handle, *channel; handle = xml_attr( attr_names, attr_values, "handle" ); channel = xml_attr( attr_names, attr_values, "channel" ); if( xd->current_account && handle && channel ) { irc_channel_t *ic; if( ( ic = irc_channel_new( irc, channel ) ) && set_setstr( &ic->set, "type", "chat" ) && set_setstr( &ic->set, "chat_type", "room" ) && set_setstr( &ic->set, "account", xd->current_account->tag ) && set_setstr( &ic->set, "room", handle ) ) { /* Try to pick up some settings where possible. */ xd->current_channel = ic; } else if( ic ) irc_channel_free( ic ); } else { g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Missing attributes for %s element", element_name ); } } else { xd->unknown_tag ++; irc_rootmsg( irc, "Warning: Unknown XML tag found in configuration file (%s). " "This may happen when downgrading BitlBee versions. " "This tag will be skipped and the information will be lost " "once you save your settings.", element_name ); /* g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, "Unkown element: %s", element_name ); */ } }
static xt_status handle_account(struct xt_node *node, gpointer data) { struct xml_parsedata *xd = data; char *protocol, *handle, *server, *password = NULL, *autoconnect, *tag, *locked; char *pass_b64 = NULL; unsigned char *pass_cr = NULL; int pass_len, local = 0; struct prpl *prpl = NULL; account_t *acc; struct xt_node *c; handle = xt_find_attr(node, "handle"); pass_b64 = xt_find_attr(node, "password"); server = xt_find_attr(node, "server"); autoconnect = xt_find_attr(node, "autoconnect"); tag = xt_find_attr(node, "tag"); locked = xt_find_attr(node, "locked"); protocol = xt_find_attr(node, "protocol"); if (protocol) { prpl = find_protocol(protocol); if (!prpl) { irc_rootmsg(xd->irc, "Error loading user config: Protocol not found: `%s'", protocol); return XT_ABORT; } local = protocol_account_islocal(protocol); } if (!handle || !pass_b64 || !protocol || !prpl) { return XT_ABORT; } pass_len = base64_decode(pass_b64, (unsigned char **) &pass_cr); if (xd->irc->auth_backend) { password = g_strdup((char *)pass_cr); } else { 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); g_free(password); handle_settings(node, &acc->set); for (c = node->children; (c = xt_find_node(c, "buddy")); c = c->next) { char *handle, *nick; handle = xt_find_attr(c, "handle"); nick = xt_find_attr(c, "nick"); if (handle && nick) { nick_set_raw(acc, handle, nick); } else { return XT_ABORT; } } return XT_HANDLED; }