jabberd2  2.2.16
c2s/authreg.c
Go to the documentation of this file.
00001 /*
00002  * jabberd - Jabber Open Source Server
00003  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
00004  *                    Ryan Eatmon, Robert Norris
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
00019  */
00020 
00021 #include "c2s.h"
00022 #include <stringprep.h>
00023 #ifdef _WIN32
00024   #include <windows.h>
00025   #define LIBRARY_DIR "."
00026 #else
00027   #include <dlfcn.h>
00028 #endif
00029 
00030 /* authreg module manager */
00031 
00032 typedef struct _authreg_error_st {
00033     char        *class;
00034     char        *name;
00035     char        *code;
00036     char        *uri;
00037 } *authreg_error_t;
00038 
00040 authreg_t authreg_init(c2s_t c2s, char *name) {
00041     char mod_fullpath[PATH_MAX], *modules_path;
00042     ar_module_init_fn init_fn = NULL;
00043     authreg_t ar;
00044     void *handle;
00045 
00046     /* load authreg module */
00047     modules_path = config_get_one(c2s->config, "authreg.path", 0);
00048     if (modules_path != NULL)
00049         log_write(c2s->log, LOG_NOTICE, "modules search path: %s", modules_path);
00050     else
00051         log_write(c2s->log, LOG_NOTICE, "modules search path undefined, using default: "LIBRARY_DIR);
00052 
00053     log_write(c2s->log, LOG_INFO, "loading '%s' authreg module", name);
00054 #ifndef _WIN32
00055     if (modules_path != NULL)
00056         snprintf(mod_fullpath, PATH_MAX, "%s/authreg_%s.so", modules_path, name);
00057     else
00058         snprintf(mod_fullpath, PATH_MAX, "%s/authreg_%s.so", LIBRARY_DIR, name);
00059     handle = dlopen(mod_fullpath, RTLD_LAZY);
00060     if (handle != NULL)
00061         init_fn = dlsym(handle, "ar_init");
00062 #else
00063     if (modules_path != NULL)
00064         snprintf(mod_fullpath, PATH_MAX, "%s\\authreg_%s.dll", modules_path, name);
00065     else
00066         snprintf(mod_fullpath, PATH_MAX, "authreg_%s.dll", name);
00067     handle = (void*) LoadLibrary(mod_fullpath);
00068     if (handle != NULL)
00069         init_fn = (ar_module_init_fn)GetProcAddress((HMODULE) handle, "ar_init");
00070 #endif
00071 
00072     if (handle != NULL && init_fn != NULL) {
00073         log_debug(ZONE, "preloaded module '%s' (not initialized yet)", name);
00074     } else {
00075 #ifndef _WIN32
00076         log_write(c2s->log, LOG_ERR, "failed loading authreg module '%s' (%s)", name, dlerror());
00077         if (handle != NULL)
00078             dlclose(handle);
00079 #else
00080         log_write(c2s->log, LOG_ERR, "failed loading authreg module '%s' (errcode: %x)", name, GetLastError());
00081         if (handle != NULL)
00082             FreeLibrary((HMODULE) handle);
00083 #endif
00084         return NULL;
00085     }
00086 
00087     /* make a new one */
00088     ar = (authreg_t) calloc(1, sizeof(struct authreg_st));
00089 
00090     ar->c2s = c2s;
00091 
00092     /* call the initialiser */
00093     if((init_fn)(ar) != 0)
00094     {
00095         log_write(c2s->log, LOG_ERR, "failed to initialize auth module '%s'", name);
00096         authreg_free(ar);
00097         return NULL;
00098     }
00099 
00100     /* we need user_exists(), at the very least */
00101     if(ar->user_exists == NULL)
00102     {
00103         log_write(c2s->log, LOG_ERR, "auth module '%s' has no check for user existence", name);
00104         authreg_free(ar);
00105         return NULL;
00106     }
00107     
00108     /* its good */
00109     log_write(c2s->log, LOG_NOTICE, "initialized auth module '%s'", name);
00110 
00111     return ar;
00112 }
00113 
00115 void authreg_free(authreg_t ar) {
00116     if (ar) {
00117         if(ar->free != NULL) (ar->free)(ar);
00118         free(ar);
00119     }
00120 }
00121 
00123 inline static void _authreg_auth_log(c2s_t c2s, sess_t sess, char *method, char *username, char *resource, int success) {
00124     log_write(c2s->log, LOG_NOTICE, "[%d] %s authentication %s: %s@%s/%s %s:%d%s%s",
00125         sess->s->tag, method, success ? "succeeded" : "failed",
00126         username, sess->host->realm, resource,
00127         sess->s->ip, sess->s->port,
00128         sess->s->ssf ? " TLS" : "", sess->s->compressed ? " ZLIB" : ""
00129     );
00130 }
00131 
00133 static void _authreg_auth_get(c2s_t c2s, sess_t sess, nad_t nad) {
00134     int ns, elem, attr;
00135     char username[1024], id[128];
00136     int ar_mechs;
00137 
00138     /* can't auth if they're active */
00139     if(sess->active) {
00140         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_NOT_ALLOWED), 0));
00141         return;
00142     }
00143 
00144     /* sort out the username */
00145     ns = nad_find_scoped_namespace(nad, uri_AUTH, NULL);
00146     elem = nad_find_elem(nad, 1, ns, "username", 1);
00147     if(elem < 0)
00148     {
00149         log_debug(ZONE, "auth get with no username, bouncing it");
00150 
00151         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_BAD_REQUEST), 0));
00152 
00153         return;
00154     }
00155 
00156     snprintf(username, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
00157     if(stringprep_xmpp_nodeprep(username, 1024) != 0) {
00158         log_debug(ZONE, "auth get username failed nodeprep, bouncing it");
00159         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_JID_MALFORMED), 0));
00160         return;
00161     }
00162 
00163     ar_mechs = c2s->ar_mechanisms;
00164     if (sess->s->ssf>0) 
00165         ar_mechs = ar_mechs | c2s->ar_ssl_mechanisms;
00166         
00167     /* no point going on if we have no mechanisms */
00168     if(!(ar_mechs & (AR_MECH_TRAD_PLAIN | AR_MECH_TRAD_DIGEST))) {
00169         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_FORBIDDEN), 0));
00170         return;
00171     }
00172     
00173     /* do we have the user? */
00174     if((c2s->ar->user_exists)(c2s->ar, username, sess->host->realm) == 0) {
00175         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_OLD_UNAUTH), 0));
00176         return;
00177     }
00178 
00179     /* extract the id */
00180     attr = nad_find_attr(nad, 0, -1, "id", NULL);
00181     if(attr >= 0)
00182         snprintf(id, 128, "%.*s", NAD_AVAL_L(nad, attr), NAD_AVAL(nad, attr));
00183 
00184     nad_free(nad);
00185 
00186     /* build a result packet */
00187     nad = nad_new();
00188 
00189     ns = nad_add_namespace(nad, uri_CLIENT, NULL);
00190 
00191     nad_append_elem(nad, ns, "iq", 0);
00192     nad_append_attr(nad, -1, "type", "result");
00193 
00194     if(attr >= 0)
00195         nad_append_attr(nad, -1, "id", id);
00196 
00197     ns = nad_add_namespace(nad, uri_AUTH, NULL);
00198     nad_append_elem(nad, ns, "query", 1);
00199     
00200     nad_append_elem(nad, ns, "username", 2);
00201     nad_append_cdata(nad, username, strlen(username), 3);
00202 
00203     nad_append_elem(nad, ns, "resource", 2);
00204 
00205     /* fill out the packet with available auth mechanisms */
00206     if(ar_mechs & AR_MECH_TRAD_PLAIN && (c2s->ar->get_password != NULL || c2s->ar->check_password != NULL))
00207         nad_append_elem(nad, ns, "password", 2);
00208 
00209     if(ar_mechs & AR_MECH_TRAD_DIGEST && c2s->ar->get_password != NULL)
00210         nad_append_elem(nad, ns, "digest", 2);
00211 
00212     /* give it back to the client */
00213     sx_nad_write(sess->s, nad);
00214 
00215     return;
00216 }
00217 
00219 static void _authreg_auth_set(c2s_t c2s, sess_t sess, nad_t nad) {
00220     int ns, elem, attr, authd = 0;
00221     char username[1024], resource[1024], str[1024], hash[280];
00222     int ar_mechs;
00223 
00224     /* can't auth if they're active */
00225     if(sess->active) {
00226         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_NOT_ALLOWED), 0));
00227         return;
00228     }
00229 
00230     ns = nad_find_scoped_namespace(nad, uri_AUTH, NULL);
00231 
00232     /* sort out the username */
00233     elem = nad_find_elem(nad, 1, ns, "username", 1);
00234     if(elem < 0)
00235     {
00236         log_debug(ZONE, "auth set with no username, bouncing it");
00237 
00238         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_BAD_REQUEST), 0));
00239 
00240         return;
00241     }
00242 
00243     snprintf(username, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
00244     if(stringprep_xmpp_nodeprep(username, 1024) != 0) {
00245         log_debug(ZONE, "auth set username failed nodeprep, bouncing it");
00246         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_JID_MALFORMED), 0));
00247         return;
00248     }
00249 
00250     /* make sure we have the resource */
00251     elem = nad_find_elem(nad, 1, ns, "resource", 1);
00252     if(elem < 0)
00253     {
00254         log_debug(ZONE, "auth set with no resource, bouncing it");
00255 
00256         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_BAD_REQUEST), 0));
00257 
00258         return;
00259     }
00260 
00261     snprintf(resource, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
00262     if(stringprep_xmpp_resourceprep(resource, 1024) != 0) {
00263         log_debug(ZONE, "auth set resource failed resourceprep, bouncing it");
00264         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_JID_MALFORMED), 0));
00265         return;
00266     }
00267 
00268     ar_mechs = c2s->ar_mechanisms;
00269     if (sess->s->ssf > 0)
00270         ar_mechs = ar_mechs | c2s->ar_ssl_mechanisms;
00271     
00272     /* no point going on if we have no mechanisms */
00273     if(!(ar_mechs & (AR_MECH_TRAD_PLAIN | AR_MECH_TRAD_DIGEST))) {
00274         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_FORBIDDEN), 0));
00275         return;
00276     }
00277     
00278     /* do we have the user? */
00279     if((c2s->ar->user_exists)(c2s->ar, username, sess->host->realm) == 0) {
00280         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_OLD_UNAUTH), 0));
00281         return;
00282     }
00283     
00284     /* digest auth */
00285     if(!authd && ar_mechs & AR_MECH_TRAD_DIGEST && c2s->ar->get_password != NULL)
00286     {
00287         elem = nad_find_elem(nad, 1, ns, "digest", 1);
00288         if(elem >= 0)
00289         {
00290             if((c2s->ar->get_password)(c2s->ar, username, sess->host->realm, str) == 0)
00291             {
00292                 snprintf(hash, 280, "%s%s", sess->s->id, str);
00293                 shahash_r(hash, hash);
00294 
00295                 if(strlen(hash) == NAD_CDATA_L(nad, elem) && strncmp(hash, NAD_CDATA(nad, elem), NAD_CDATA_L(nad, elem)) == 0)
00296                 {
00297                     log_debug(ZONE, "digest auth succeeded");
00298                     authd = 1;
00299                     _authreg_auth_log(c2s, sess, "traditional.digest", username, resource, TRUE);
00300                 }
00301             }
00302         }
00303     }
00304 
00305     /* plaintext auth (compare) */
00306     if(!authd && ar_mechs & AR_MECH_TRAD_PLAIN && c2s->ar->get_password != NULL)
00307     {
00308         elem = nad_find_elem(nad, 1, ns, "password", 1);
00309         if(elem >= 0)
00310         {
00311             if((c2s->ar->get_password)(c2s->ar, username, sess->host->realm, str) == 0 && strlen(str) == NAD_CDATA_L(nad, elem) && strncmp(str, NAD_CDATA(nad, elem), NAD_CDATA_L(nad, elem)) == 0)
00312             {
00313                 log_debug(ZONE, "plaintext auth (compare) succeeded");
00314                 authd = 1;
00315                 _authreg_auth_log(c2s, sess, "traditional.plain(compare)", username, resource, TRUE);
00316             }
00317         }
00318     }
00319 
00320     /* plaintext auth (check) */
00321     if(!authd && ar_mechs & AR_MECH_TRAD_PLAIN && c2s->ar->check_password != NULL)
00322     {
00323         elem = nad_find_elem(nad, 1, ns, "password", 1);
00324         if(elem >= 0)
00325         {
00326             snprintf(str, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
00327             if((c2s->ar->check_password)(c2s->ar, username, sess->host->realm, str) == 0)
00328             {
00329                 log_debug(ZONE, "plaintext auth (check) succeded");
00330                 authd = 1;
00331                 _authreg_auth_log(c2s, sess, "traditional.plain", username, resource, TRUE);
00332             }
00333         }
00334     }
00335 
00336     /* now, are they authenticated? */
00337     if(authd)
00338     {
00339         /* create new bound jid holder */
00340         if(sess->resources == NULL) {
00341             sess->resources = (bres_t) calloc(1, sizeof(struct bres_st));
00342         }
00343 
00344         /* our local id */
00345         sprintf(sess->resources->c2s_id, "%d", sess->s->tag);
00346 
00347         /* the full user jid for this session */
00348         sess->resources->jid = jid_new(sess->s->req_to, -1);
00349         jid_reset_components(sess->resources->jid, username, sess->resources->jid->domain, resource);
00350 
00351         log_write(sess->c2s->log, LOG_NOTICE, "[%d] requesting session: jid=%s", sess->s->tag, jid_full(sess->resources->jid));
00352 
00353         /* build a result packet, we'll send this back to the client after we have a session for them */
00354         sess->result = nad_new();
00355 
00356         ns = nad_add_namespace(sess->result, uri_CLIENT, NULL);
00357 
00358         nad_append_elem(sess->result, ns, "iq", 0);
00359         nad_set_attr(sess->result, 0, -1, "type", "result", 6);
00360 
00361         attr = nad_find_attr(nad, 0, -1, "id", NULL);
00362         if(attr >= 0)
00363             nad_set_attr(sess->result, 0, -1, "id", NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));
00364 
00365         /* start a session with the sm */
00366         sm_start(sess, sess->resources);
00367 
00368         /* finished with the nad */
00369         nad_free(nad);
00370 
00371         return;
00372     }
00373 
00374     _authreg_auth_log(c2s, sess, "traditional", username, resource, FALSE);
00375 
00376     /* auth failed, so error */
00377     sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_OLD_UNAUTH), 0));
00378 
00379     return;
00380 }
00381 
00383 static void _authreg_register_get(c2s_t c2s, sess_t sess, nad_t nad) {
00384     int attr, ns;
00385     char id[128];
00386 
00387     /* registrations can happen if reg is enabled and we can create users and set passwords */
00388     if(sess->active || !(c2s->ar->set_password != NULL && c2s->ar->create_user != NULL && (sess->host->ar_register_enable || sess->host->ar_register_oob))) {
00389         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_NOT_ALLOWED), 0));
00390         return;
00391     }
00392 
00393     /* extract the id */
00394     attr = nad_find_attr(nad, 0, -1, "id", NULL);
00395     if(attr >= 0)
00396         snprintf(id, 128, "%.*s", NAD_AVAL_L(nad, attr), NAD_AVAL(nad, attr));
00397 
00398     nad_free(nad);
00399 
00400     /* build a result packet */
00401     nad = nad_new();
00402 
00403     ns = nad_add_namespace(nad, uri_CLIENT, NULL);
00404 
00405     nad_append_elem(nad, ns, "iq", 0);
00406     nad_append_attr(nad, -1, "type", "result");
00407 
00408     if(attr >= 0)
00409         nad_append_attr(nad, -1, "id", id);
00410 
00411     ns = nad_add_namespace(nad, uri_REGISTER, NULL);
00412     nad_append_elem(nad, ns, "query", 1);
00413     
00414     nad_append_elem(nad, ns, "instructions", 2);
00415     nad_append_cdata(nad, sess->host->ar_register_instructions, strlen(sess->host->ar_register_instructions), 3);
00416 
00417     if(sess->host->ar_register_enable) {
00418         nad_append_elem(nad, ns, "username", 2);
00419         nad_append_elem(nad, ns, "password", 2);
00420     }
00421 
00422     if(sess->host->ar_register_oob) {
00423         int ns = nad_add_namespace(nad, uri_OOB, NULL);
00424         nad_append_elem(nad, ns, "x", 2);
00425         nad_append_elem(nad, ns, "url", 3);
00426         nad_append_cdata(nad, sess->host->ar_register_oob, strlen(sess->host->ar_register_oob), 4);
00427     }
00428 
00429     /* give it back to the client */
00430     sx_nad_write(sess->s, nad);
00431 }
00432 
00434 static void _authreg_register_set(c2s_t c2s, sess_t sess, nad_t nad)
00435 {
00436     int ns = 0, elem, attr;
00437     char username[1024], password[1024];
00438 
00439     /* if we're not configured for registration (or pw changes), or we can't set passwords, fail outright */
00440     if(!(sess->host->ar_register_enable || sess->host->ar_register_password) || c2s->ar->set_password == NULL) {
00441         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_NOT_ALLOWED), 0));
00442         return;
00443     }
00444 
00445     ns = nad_find_scoped_namespace(nad, uri_REGISTER, NULL);
00446 
00447     /* removals */
00448     if(sess->active && nad_find_elem(nad, 1, ns, "remove", 1) >= 0) {
00449         /* only if full reg is enabled */
00450         if(!sess->host->ar_register_enable) {
00451             sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_NOT_ALLOWED), 0));
00452             return;
00453         }
00454 
00455         log_debug(ZONE, "user remove requested");
00456 
00457         /* make sure we can delete them */
00458         if(c2s->ar->delete_user == NULL) {
00459             sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_NOT_ALLOWED), 0));
00460             return;
00461         }
00462 
00463         /* otherwise, delete them */
00464         if((c2s->ar->delete_user)(c2s->ar, sess->resources->jid->node, sess->host->realm) != 0) {
00465             log_debug(ZONE, "user delete failed");
00466             sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_INTERNAL_SERVER_ERROR), 0));
00467             return;
00468         }
00469 
00470         log_write(c2s->log, LOG_NOTICE, "[%d] deleted user: user=%s; realm=%s", sess->s->tag, sess->resources->jid->node, sess->host->realm);
00471 
00472         log_write(c2s->log, LOG_NOTICE, "[%d] registration remove succeeded, requesting user deletion: jid=%s", sess->s->tag, jid_user(sess->resources->jid));
00473 
00474         /* make a result nad */
00475         sess->result = nad_new();
00476 
00477         ns = nad_add_namespace(sess->result, uri_CLIENT, NULL);
00478 
00479         nad_append_elem(sess->result, ns, "iq", 0);
00480         nad_set_attr(sess->result, 0, -1, "type", "result", 6);
00481 
00482         /* extract the id */
00483         attr = nad_find_attr(nad, 0, -1, "id", NULL);
00484         if(attr >= 0)
00485             nad_set_attr(sess->result, 0, -1, "id", NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));
00486 
00487         nad_free(nad);
00488 
00489         sx_nad_write(sess->s, sess->result);
00490         sess->result = NULL;
00491 
00492         /* get the sm to delete them (it will force their sessions to end) */
00493         sm_delete(sess, sess->resources);
00494 
00495         return;
00496     }
00497 
00498     /* username is required */
00499     elem = nad_find_elem(nad, 1, ns, "username", 1);
00500     if(elem < 0)
00501     {
00502         log_debug(ZONE, "register set with no username, bouncing it");
00503         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_BAD_REQUEST), 0));
00504         return;
00505     }
00506 
00507     snprintf(username, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
00508     if(stringprep_xmpp_nodeprep(username, 1024) != 0) {
00509         log_debug(ZONE, "register set username failed nodeprep, bouncing it");
00510         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_JID_MALFORMED), 0));
00511         return;
00512     }
00513 
00514     elem = nad_find_elem(nad, 1, ns, "password", 1);
00515     if(elem < 0)
00516     {
00517         log_debug(ZONE, "register set with no password, bouncing it");
00518         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_BAD_REQUEST), 0));
00519         return;
00520     }
00521 
00522     /* if they're already auth'd, its a password change */
00523     if(sess->active)
00524     {
00525         /* confirm that the username matches their auth id */
00526         if(strcmp(username, sess->resources->jid->node) != 0)
00527         {
00528             log_debug(ZONE, "%s is trying to change password for %s, bouncing it", jid_full(sess->resources->jid), username);
00529             sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_OLD_UNAUTH), 0));
00530             return;
00531         }
00532     }
00533 
00534     /* can't go on if we're not doing full reg */
00535     else if(!sess->host->ar_register_enable) {
00536         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_NOT_ALLOWED), 0));
00537         return;
00538     }
00539 
00540     /* if they exist, bounce */
00541     else if((c2s->ar->user_exists)(c2s->ar, username, sess->host->realm))
00542     {
00543         log_debug(ZONE, "attempt to register %s, but they already exist", username);
00544         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_CONFLICT), 0));
00545         return;
00546     }
00547 
00548     /* make sure we can create them */
00549     else if(c2s->ar->create_user == NULL)
00550     {
00551         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_NOT_ALLOWED), 0));
00552         return;
00553     }
00554 
00555     /* otherwise, create them */
00556     else if((c2s->ar->create_user)(c2s->ar, username, sess->host->realm) != 0)
00557     {
00558         log_debug(ZONE, "user create failed");
00559         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_INTERNAL_SERVER_ERROR), 0));
00560         return;
00561     }
00562 
00563     else
00564         log_write(c2s->log, LOG_NOTICE, "[%d] created user: user=%s; realm=%s", sess->s->tag, username, sess->host->realm);
00565 
00566     /* extract the password */
00567     snprintf(password, 257, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
00568 
00569     /* change it */
00570     if((c2s->ar->set_password)(c2s->ar, username, sess->host->realm, password) != 0)
00571     {
00572         log_debug(ZONE, "password store failed");
00573         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_INTERNAL_SERVER_ERROR), 0));
00574         return;
00575     }
00576 
00577     log_debug(ZONE, "updated auth creds for %s", username);
00578 
00579     /* make a result nad */
00580     sess->result = nad_new();
00581 
00582     ns = nad_add_namespace(sess->result, uri_CLIENT, NULL);
00583 
00584     nad_append_elem(sess->result, ns, "iq", 0);
00585     nad_set_attr(sess->result, 0, -1, "type", "result", 6);
00586 
00587     /* extract the id */
00588     attr = nad_find_attr(nad, 0, -1, "id", NULL);
00589     if(attr >= 0)
00590         nad_set_attr(sess->result, 0, -1, "id", NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));
00591 
00592     /* if they're active, then this was just a password change, and we're done */
00593     if(sess->active) {
00594         log_write(c2s->log, LOG_NOTICE, "[%d] password changed: jid=%s", sess->s->tag, jid_user(sess->resources->jid));
00595         sx_nad_write(sess->s, sess->result);
00596         sess->result = NULL;
00597         return;
00598     }
00599 
00600     /* create new bound jid holder */
00601     if(sess->resources == NULL) {
00602         sess->resources = (bres_t) calloc(1, sizeof(struct bres_st));
00603     }
00604 
00605     /* our local id */
00606     sprintf(sess->resources->c2s_id, "%d", sess->s->tag);
00607 
00608     /* the user jid for this transaction */
00609     sess->resources->jid = jid_new(sess->s->req_to, -1);
00610     jid_reset_components(sess->resources->jid, username, sess->resources->jid->domain, sess->resources->jid->resource);
00611 
00612     log_write(c2s->log, LOG_NOTICE, "[%d] registration succeeded, requesting user creation: jid=%s", sess->s->tag, jid_user(sess->resources->jid));
00613 
00614     /* get the sm to create them */
00615     sm_create(sess, sess->resources);
00616 
00617     nad_free(nad);
00618 
00619     return;
00620 }
00621 
00626 int authreg_process(c2s_t c2s, sess_t sess, nad_t nad) {
00627     int ns, query, type, authreg = -1, getset = -1;
00628 
00629     /* need iq */
00630     if(NAD_ENAME_L(nad, 0) != 2 || strncmp("iq", NAD_ENAME(nad, 0), 2) != 0)
00631         return 1;
00632 
00633     /* only want auth or register packets */
00634     if((ns = nad_find_scoped_namespace(nad, uri_AUTH, NULL)) >= 0 && (query = nad_find_elem(nad, 0, ns, "query", 1)) >= 0)
00635         authreg = 0;
00636     else if((ns = nad_find_scoped_namespace(nad, uri_REGISTER, NULL)) >= 0 && (query = nad_find_elem(nad, 0, ns, "query", 1)) >= 0)
00637         authreg = 1;
00638     else
00639         return 1;
00640 
00641     /* if its to someone else, pass it */
00642     if(nad_find_attr(nad, 0, -1, "to", NULL) >= 0 && nad_find_attr(nad, 0, -1, "to", sess->s->req_to) < 0)
00643         return 1;
00644 
00645     /* need a type */
00646     if((type = nad_find_attr(nad, 0, -1, "type", NULL)) < 0 || NAD_AVAL_L(nad, type) != 3)
00647     {
00648         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_BAD_REQUEST), 0));
00649         return 0;
00650     }
00651 
00652     /* get or set? */
00653     if(strncmp("get", NAD_AVAL(nad, type), NAD_AVAL_L(nad, type)) == 0)
00654         getset = 0;
00655     else if(strncmp("set", NAD_AVAL(nad, type), NAD_AVAL_L(nad, type)) == 0)
00656         getset = 1;
00657     else
00658     {
00659         sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_BAD_REQUEST), 0));
00660         return 0;
00661     }
00662 
00663     /* hand to the correct handler */
00664     if(authreg == 0) {
00665         /* can't do iq:auth after sasl auth */
00666         if(sess->sasl_authd) {
00667             sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_NOT_ALLOWED), 0));
00668             return 0;
00669         }
00670 
00671         if(getset == 0) {
00672             log_debug(ZONE, "auth get");
00673             _authreg_auth_get(c2s, sess, nad);
00674         } else if(getset == 1) {
00675             log_debug(ZONE, "auth set");
00676             _authreg_auth_set(c2s, sess, nad);
00677         }
00678     }
00679 
00680     if(authreg == 1) {
00681         if(getset == 0) {
00682             log_debug(ZONE, "register get");
00683             _authreg_register_get(c2s, sess, nad);
00684         } else if(getset == 1) {
00685             log_debug(ZONE, "register set");
00686             _authreg_register_set(c2s, sess, nad);
00687         }
00688     }
00689 
00690     /* handled */
00691     return 0;
00692 }