/* * atheme.logout * * XML inputs: * authcookie, and account name. * * XML outputs: * fault 1 - insufficient parameters * fault 3 - unknown user * fault 15 - validation failed * default - success message * * Side Effects: * an authcookie ticket is destroyed. */ static int xmlrpcmethod_logout(void *conn, int parc, char *parv[]) { authcookie_t *ac; myuser_t *mu; if (parc < 2) { xmlrpc_generic_error(fault_needmoreparams, "Insufficient parameters."); return 0; } if ((mu = myuser_find(parv[1])) == NULL) { xmlrpc_generic_error(fault_nosuch_source, "Unknown user."); return 0; } if (authcookie_validate(parv[0], mu) == false) { xmlrpc_generic_error(fault_badauthcookie, "Invalid authcookie for this account."); return 0; } logcommand_external(nicksvs.me, "xmlrpc", conn, NULL, mu, CMDLOG_LOGIN, "LOGOUT"); ac = authcookie_find(parv[0], mu); authcookie_destroy(ac); xmlrpc_send_string("You are now logged out."); return 0; }
/* * atheme.login * * XML Inputs: * account name, password, source ip (optional) * * XML Outputs: * fault 1 - insufficient parameters * fault 3 - account is not registered * fault 5 - invalid username and password * fault 6 - account is frozen * default - success (authcookie) * * Side Effects: * an authcookie ticket is created for the myuser_t. * the user's lastlogin is updated */ static int xmlrpcmethod_login(void *conn, int parc, char *parv[]) { myuser_t *mu; authcookie_t *ac; const char *sourceip; if (parc < 2) { xmlrpc_generic_error(fault_needmoreparams, "Insufficient parameters."); return 0; } sourceip = parc >= 3 && *parv[2] != '\0' ? parv[2] : NULL; if (!(mu = myuser_find(parv[0]))) { xmlrpc_generic_error(fault_nosuch_source, "The account is not registered."); return 0; } if (metadata_find(mu, "private:freeze:freezer") != NULL) { logcommand_external(nicksvs.me, "xmlrpc", conn, sourceip, NULL, CMDLOG_LOGIN, "failed LOGIN to \2%s\2 (frozen)", entity(mu)->name); xmlrpc_generic_error(fault_noprivs, "The account has been frozen."); return 0; } if (!verify_password(mu, parv[1])) { sourceinfo_t *si; logcommand_external(nicksvs.me, "xmlrpc", conn, sourceip, NULL, CMDLOG_LOGIN, "failed LOGIN to \2%s\2 (bad password)", entity(mu)->name); xmlrpc_generic_error(fault_authfail, "The password is not valid for this account."); si = sourceinfo_create(); si->service = NULL; si->sourcedesc = parv[2] != NULL && *parv[2] ? parv[2] : NULL; si->connection = conn; si->v = &xmlrpc_vtable; si->force_language = language_find("en"); bad_password(si, mu); object_unref(si); return 0; } mu->lastlogin = CURRTIME; ac = authcookie_create(mu); logcommand_external(nicksvs.me, "xmlrpc", conn, sourceip, mu, CMDLOG_LOGIN, "LOGIN"); xmlrpc_send_string(ac->ticket); return 0; }
/* * atheme.privset * * XML inputs: * authcookie, account name, source ip * * XML outputs: * depends on command * * Side Effects: * command is executed */ static int xmlrpcmethod_privset(void *conn, int parc, char *parv[]) { myuser_t *mu; int i; for (i = 0; i < parc; i++) { if (strchr(parv[i], '\r') || strchr(parv[i], '\n')) { xmlrpc_generic_error(fault_badparams, "Invalid parameters."); return 0; } } if (parc < 2) { xmlrpc_generic_error(fault_needmoreparams, "Insufficient parameters."); return 0; } if (*parv[1] != '\0' && strlen(parv[0]) > 1) { if ((mu = myuser_find(parv[1])) == NULL) { xmlrpc_generic_error(fault_nosuch_source, "Unknown user."); return 0; } if (authcookie_validate(parv[0], mu) == false) { xmlrpc_generic_error(fault_badauthcookie, "Invalid authcookie for this account."); return 0; } } else mu = NULL; if (mu == NULL || !is_soper(mu)) { /* no privileges */ xmlrpc_send_string(""); return 0; } xmlrpc_send_string(mu->soper->operclass->privs); return 0; }
/* * atheme.login * * XML Inputs: * account name, password, source ip (optional) * * XML Outputs: * fault 1 - insufficient parameters * fault 3 - account is not registered * fault 5 - invalid username and password * fault 6 - account is frozen * default - success (authcookie) * * Side Effects: * an authcookie ticket is created for the myuser_t. * the user's lastlogin is updated */ static int xmlrpcmethod_login(void *conn, int parc, char *parv[]) { myuser_t *mu; authcookie_t *ac; const char *sourceip; if (parc < 2) { xmlrpc_generic_error(fault_needmoreparams, "Insufficient parameters."); return 0; } sourceip = parc >= 3 && *parv[2] != '\0' ? parv[2] : NULL; if (!(mu = myuser_find(parv[0]))) { xmlrpc_generic_error(fault_nosuch_source, "The account is not registered."); return 0; } if (metadata_find(mu, "private:freeze:freezer") != NULL) { logcommand_external(nicksvs.me, "xmlrpc", conn, sourceip, NULL, CMDLOG_LOGIN, "failed LOGIN to %s (frozen)", mu->name); xmlrpc_generic_error(fault_noprivs, "The account has been frozen."); return 0; } if (!verify_password(mu, parv[1])) { logcommand_external(nicksvs.me, "xmlrpc", conn, sourceip, NULL, CMDLOG_LOGIN, "failed LOGIN to %s (bad password)", mu->name); xmlrpc_generic_error(fault_authfail, "The password is not valid for this account."); return 0; } mu->lastlogin = CURRTIME; ac = authcookie_create(mu); logcommand_external(nicksvs.me, "xmlrpc", conn, sourceip, mu, CMDLOG_LOGIN, "LOGIN"); xmlrpc_send_string(ac->ticket); return 0; }
/* * atheme.ison * * XML inputs: * nickname * * XML outputs: * boolean: if nickname is online * string: if nickname is authenticated, what entity they are authed to, * else '*' */ static int xmlrpcmethod_ison(void *conn, int parc, char *parv[]) { user_t *u; int i; char buf[XMLRPC_BUFSIZE], buf2[XMLRPC_BUFSIZE]; for (i = 0; i < parc; i++) { if (strchr(parv[i], '\r') || strchr(parv[i], '\n')) { xmlrpc_generic_error(fault_badparams, "Invalid parameters."); return 0; } } if (parc < 1) { xmlrpc_generic_error(fault_needmoreparams, "Insufficient parameters."); return 0; } u = user_find(parv[0]); if (u == NULL) { xmlrpc_boolean(buf, false); xmlrpc_string(buf2, "*"); xmlrpc_send(2, buf, buf2); return 0; } xmlrpc_boolean(buf, true); xmlrpc_string(buf2, u->myuser != NULL ? entity(u->myuser)->name : "*"); xmlrpc_send(2, buf, buf2); return 0; }
static void xmlrpc_command_fail(sourceinfo_t *si, cmd_faultcode_t code, const char *message) { connection_t *cptr; struct httpddata *hd; char *newmessage; cptr = si->connection; hd = cptr->userdata; if (hd->sent_reply) return; newmessage = xmlrpc_normalizeBuffer(message); xmlrpc_generic_error(code, newmessage); free(newmessage); hd->sent_reply = true; }
static void xmlrpc_command_fail(sourceinfo_t *si, faultcode_t code, const char *message) { connection_t *cptr; struct httpddata *hd; char newmessage[256]; int i; const char *p; cptr = si->connection; hd = cptr->userdata; if (hd->sent_reply) return; i = 0, p = message; while (i < 255 && *p != '\0') if (*p > '\0' && *p < ' ') p++; else newmessage[i++] = *p, p++; newmessage[i] = '\0'; xmlrpc_generic_error(code, newmessage); hd->sent_reply = true; }
void xmlrpc_process(char *buffer, void *userdata) { int retVal = 0; XMLRPCCmd *current = NULL; XMLRPCCmd *xml; char *tmp; int ac; char **av = NULL; char *name = NULL; xmlrpc_error_code = 0; if (!buffer) { xmlrpc_error_code = -1; return; } tmp = xmlrpc_parse(buffer); if (tmp) { name = xmlrpc_method(tmp); if (name) { xml = mowgli_patricia_retrieve(XMLRPCCMD, name); if (xml) { ac = xmlrpc_split_buf(tmp, &av); if (xml->func) { retVal = xml->func(userdata, ac, av); if (retVal == XMLRPC_CONT) { current = xml->next; while (current && current->func && retVal == XMLRPC_CONT) { retVal = current->func(userdata, ac, av); current = current->next; } } else { /* we assume that XMLRPC_STOP means the handler has given no output */ xmlrpc_error_code = -7; xmlrpc_generic_error(xmlrpc_error_code, "XMLRPC error: First eligible function returned XMLRPC_STOP"); } } else { xmlrpc_error_code = -6; xmlrpc_generic_error(xmlrpc_error_code, "XMLRPC error: Method has no registered function"); } } else { xmlrpc_error_code = -4; xmlrpc_generic_error(xmlrpc_error_code, "XMLRPC error: Unknown routine called"); } } else { xmlrpc_error_code = -3; xmlrpc_generic_error(xmlrpc_error_code, "XMLRPC error: Missing methodRequest or methodName."); } } else { xmlrpc_error_code = -2; xmlrpc_generic_error(xmlrpc_error_code, "XMLRPC error: Invalid document end at line 1"); } free(av); free(tmp); free(name); }
/* * atheme.metadata * * XML inputs: * entity name, UID or channel name * metadata key * metadata value (optional) * * XML outputs: * string: metadata value */ static int xmlrpcmethod_metadata(void *conn, int parc, char *parv[]) { metadata_t *md; int i; char buf[XMLRPC_BUFSIZE]; for (i = 0; i < parc; i++) { if (strchr(parv[i], '\r') || strchr(parv[i], '\n')) { xmlrpc_generic_error(fault_badparams, "Invalid parameters."); return 0; } } if (parc < 2) { xmlrpc_generic_error(fault_needmoreparams, "Insufficient parameters."); return 0; } if (*parv[0] == '#') { mychan_t *mc; mc = mychan_find(parv[0]); if (mc == NULL) { xmlrpc_generic_error(fault_nosuch_source, "No channel registration was found for the provided channel name."); return 0; } md = metadata_find(mc, parv[1]); } else { myentity_t *mt; mt = myentity_find(parv[0]); if (mt == NULL) mt = myentity_find_uid(parv[0]); if (mt == NULL) { xmlrpc_generic_error(fault_nosuch_source, "No account was found for this accountname or UID."); return 0; } md = metadata_find(mt, parv[1]); } if (md == NULL) { xmlrpc_generic_error(fault_nosuch_source, "No metadata found matching this account/channel and key."); return 0; } xmlrpc_string(buf, md->value); xmlrpc_send(1, buf); return 0; }
/* * atheme.command * * XML inputs: * authcookie, account name, source ip, service name, command name, * parameters. * * XML outputs: * depends on command * * Side Effects: * command is executed */ static int xmlrpcmethod_command(void *conn, int parc, char *parv[]) { myuser_t *mu; service_t *svs; command_t *cmd; sourceinfo_t *si; int newparc; char *newparv[20]; struct httpddata *hd = ((connection_t *)conn)->userdata; int i; for (i = 0; i < parc; i++) { if (*parv[i] == '\0' || strchr(parv[i], '\r') || strchr(parv[i], '\n')) { xmlrpc_generic_error(fault_badparams, "Invalid parameters."); return 0; } } if (parc < 5) { xmlrpc_generic_error(fault_needmoreparams, "Insufficient parameters."); return 0; } if (*parv[1] != '\0' && strlen(parv[0]) > 1) { if ((mu = myuser_find(parv[1])) == NULL) { xmlrpc_generic_error(fault_nosuch_source, "Unknown user."); return 0; } if (authcookie_validate(parv[0], mu) == false) { xmlrpc_generic_error(fault_badauthcookie, "Invalid authcookie for this account."); return 0; } } else mu = NULL; /* try literal service name first, then user-configured nickname. */ svs = service_find(parv[3]); if ((svs == NULL && (svs = service_find_nick(parv[3])) == NULL) || svs->commands == NULL) { slog(LG_DEBUG, "xmlrpcmethod_command(): invalid service %s", parv[3]); xmlrpc_generic_error(fault_nosuch_source, "Invalid service name."); return 0; } cmd = command_find(svs->commands, parv[4]); if (cmd == NULL) { xmlrpc_generic_error(fault_nosuch_source, "Invalid command name."); return 0; } memset(newparv, '\0', sizeof newparv); newparc = parc - 5; if (newparc > 20) newparc = 20; if (newparc > 0) memcpy(newparv, parv + 5, newparc * sizeof(parv[0])); si = sourceinfo_create(); si->smu = mu; si->service = svs; si->sourcedesc = parv[2][0] != '\0' ? parv[2] : NULL; si->connection = conn; si->v = &xmlrpc_vtable; si->force_language = language_find("en"); command_exec(svs, si, cmd, newparc, newparv); /* XXX: needs to be fixed up for restartable commands... */ if (!hd->sent_reply) { if (hd->replybuf != NULL) xmlrpc_send_string(hd->replybuf); else xmlrpc_generic_error(fault_unimplemented, "Command did not return a result."); } object_unref(si); return 0; }
/* * atheme.command * * XML inputs: * authcookie, account name, source ip, service name, command name, * parameters. * * XML outputs: * depends on command * * Side Effects: * command is executed */ static int xmlrpcmethod_command(void *conn, int parc, char *parv[]) { myuser_t *mu; service_t *svs; command_t *cmd; sourceinfo_t si; int newparc; char *newparv[20]; struct httpddata *hd = ((connection_t *)conn)->userdata; int i; for (i = 0; i < parc; i++) { if (strchr(parv[i], '\r') || strchr(parv[i], '\n')) { xmlrpc_generic_error(fault_badparams, "Invalid parameters."); return 0; } } if (parc < 5) { xmlrpc_generic_error(fault_needmoreparams, "Insufficient parameters."); return 0; } if (*parv[1] != '\0' && strlen(parv[0]) > 1) { if ((mu = myuser_find(parv[1])) == NULL) { xmlrpc_generic_error(fault_nosuch_source, "Unknown user."); return 0; } if (authcookie_validate(parv[0], mu) == false) { xmlrpc_generic_error(fault_badauthcookie, "Invalid authcookie for this account."); return 0; } } else mu = NULL; svs = service_find_nick(parv[3]); if (svs == NULL || svs->cmdtree == NULL) { slog(LG_DEBUG, "xmlrpcmethod_command(): invalid service %s", parv[3]); xmlrpc_generic_error(fault_nosuch_source, "Invalid service name."); return 0; } cmd = command_find(svs->cmdtree, parv[4]); if (cmd == NULL) { xmlrpc_generic_error(fault_nosuch_source, "Invalid command name."); return 0; } memset(newparv, '\0', sizeof newparv); newparc = parc - 5; if (newparc > 20) newparc = 20; if (newparc > 0) memcpy(newparv, parv + 5, newparc * sizeof(parv[0])); memset(&si, '\0', sizeof si); si.smu = mu; si.service = svs; si.sourcedesc = parv[2][0] != '\0' ? parv[2] : NULL; si.connection = conn; si.v = &xmlrpc_vtable; command_exec(svs, &si, cmd, newparc, newparv); if (!hd->sent_reply) { if (hd->replybuf != NULL) xmlrpc_send_string(hd->replybuf); else xmlrpc_generic_error(fault_unimplemented, "Command did not return a result."); } return 0; }