jabberd2  2.5.0
authreg.c
Go to the documentation of this file.
1 /*
2  * jabberd - Jabber Open Source Server
3  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
4  * Ryan Eatmon, Robert Norris
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19  */
20 
21 #include "c2s.h"
22 #include <stringprep.h>
23 #ifdef _WIN32
24  #include <windows.h>
25  #define LIBRARY_DIR "."
26 #else
27  #include <dlfcn.h>
28 #endif
29 
30 /* authreg module manager */
31 
32 typedef struct _authreg_error_st {
33  char *class;
34  char *name;
35  char *code;
36  char *uri;
38 
40 authreg_t authreg_init(c2s_t c2s, const char *name) {
41  char mod_fullpath[PATH_MAX];
42  const char *modules_path;
43  ar_module_init_fn init_fn = NULL;
44  authreg_t ar;
45  void *handle;
46 
47  /* return if already loaded */
48  ar = xhash_get(c2s->ar_modules, name);
49  if (ar) {
50  return ar->initialized ? ar : NULL;
51  }
52 
53  /* load authreg module */
54  modules_path = config_get_one(c2s->config, "authreg.path", 0);
55  if (modules_path != NULL)
56  log_write(c2s->log, LOG_NOTICE, "modules search path: %s", modules_path);
57  else
58  log_write(c2s->log, LOG_NOTICE, "modules search path undefined, using default: "LIBRARY_DIR);
59 
60  log_write(c2s->log, LOG_INFO, "loading '%s' authreg module", name);
61 #ifndef _WIN32
62  if (modules_path != NULL)
63  snprintf(mod_fullpath, PATH_MAX, "%s/authreg_%s.so", modules_path, name);
64  else
65  snprintf(mod_fullpath, PATH_MAX, "%s/authreg_%s.so", LIBRARY_DIR, name);
66  handle = dlopen(mod_fullpath, RTLD_LAZY);
67  if (handle != NULL)
68  init_fn = dlsym(handle, "ar_init");
69 #else
70  if (modules_path != NULL)
71  snprintf(mod_fullpath, PATH_MAX, "%s\\authreg_%s.dll", modules_path, name);
72  else
73  snprintf(mod_fullpath, PATH_MAX, "authreg_%s.dll", name);
74  handle = (void*) LoadLibrary(mod_fullpath);
75  if (handle != NULL)
76  init_fn = (ar_module_init_fn)GetProcAddress((HMODULE) handle, "ar_init");
77 #endif
78 
79  if (handle != NULL && init_fn != NULL) {
80  log_debug(ZONE, "preloaded module '%s' (not initialized yet)", name);
81  } else {
82 #ifndef _WIN32
83  log_write(c2s->log, LOG_ERR, "failed loading authreg module '%s' (%s)", name, dlerror());
84  if (handle != NULL)
85  dlclose(handle);
86 #else
87  log_write(c2s->log, LOG_ERR, "failed loading authreg module '%s' (errcode: %x)", name, GetLastError());
88  if (handle != NULL)
89  FreeLibrary((HMODULE) handle);
90 #endif
91  return NULL;
92  }
93 
94  /* make a new one */
95  ar = (authreg_t) pmalloco(xhash_pool(c2s->ar_modules), sizeof(struct authreg_st));
96  if(!ar) {
97  log_write(c2s->log, LOG_ERR, "cannot allocate memory for new authreg, aborting");
98  exit(1);
99  }
100 
101  ar->handle = handle;
102  ar->c2s = c2s;
103 
104  xhash_put(c2s->ar_modules, name, ar);
105 
106  /* call the initialiser */
107  if((init_fn)(ar) != 0)
108  {
109  log_write(c2s->log, LOG_ERR, "failed to initialize auth module '%s'", name);
110  authreg_free(ar);
111  return NULL;
112  }
113 
114  /* we need user_exists(), at the very least */
115  if(ar->user_exists == NULL)
116  {
117  log_write(c2s->log, LOG_ERR, "auth module '%s' has no check for user existence", name);
118  authreg_free(ar);
119  return NULL;
120  }
121 
122  /* its good */
123  ar->initialized = TRUE;
124  log_write(c2s->log, LOG_NOTICE, "initialized auth module '%s'", name);
125 
126  return ar;
127 }
128 
131  if (ar && ar->initialized) {
132  if(ar->free != NULL) (ar->free)(ar);
133  }
134 }
135 
137 inline static void _authreg_auth_log(c2s_t c2s, sess_t sess, const char *method, const char *username, const char *resource, int success) {
138  log_write(c2s->log, LOG_NOTICE, "[%d] %s authentication %s: %s@%s/%s %s:%d %s",
139  sess->s->tag, method, success ? "succeeded" : "failed",
140  username, sess->host->realm, resource,
141  sess->s->ip, sess->s->port, _sx_flags(sess->s)
142  );
143 }
144 
146 static void _authreg_auth_get(c2s_t c2s, sess_t sess, nad_t nad) {
147  int ns, elem, attr, err;
148  char username[1024], id[128];
149  int ar_mechs;
150 
151  /* can't auth if they're active */
152  if(sess->active) {
154  return;
155  }
156 
157  /* sort out the username */
158  ns = nad_find_scoped_namespace(nad, uri_AUTH, NULL);
159  elem = nad_find_elem(nad, 1, ns, "username", 1);
160  if(elem < 0)
161  {
162  log_debug(ZONE, "auth get with no username, bouncing it");
163 
165 
166  return;
167  }
168 
169  snprintf(username, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
170  if(stringprep_xmpp_nodeprep(username, 1024) != 0) {
171  log_debug(ZONE, "auth get username failed nodeprep, bouncing it");
173  return;
174  }
175 
176  ar_mechs = c2s->ar_mechanisms;
177  if (sess->s->ssf>0)
178  ar_mechs = ar_mechs | c2s->ar_ssl_mechanisms;
179 
180  /* no point going on if we have no mechanisms */
183  return;
184  }
185 
186  /* do we have the user? */
187  if((sess->host->ar->user_exists)(sess->host->ar, sess, username, sess->host->realm) == 0) {
189  return;
190  }
191 
192  /* extract the id */
193  attr = nad_find_attr(nad, 0, -1, "id", NULL);
194  if(attr >= 0)
195  snprintf(id, 128, "%.*s", NAD_AVAL_L(nad, attr), NAD_AVAL(nad, attr));
196 
197  nad_free(nad);
198 
199  /* build a result packet */
200  nad = nad_new();
201 
202  ns = nad_add_namespace(nad, uri_CLIENT, NULL);
203 
204  nad_append_elem(nad, ns, "iq", 0);
205  nad_append_attr(nad, -1, "type", "result");
206 
207  if(attr >= 0)
208  nad_append_attr(nad, -1, "id", id);
209 
210  ns = nad_add_namespace(nad, uri_AUTH, NULL);
211  nad_append_elem(nad, ns, "query", 1);
212 
213  nad_append_elem(nad, ns, "username", 2);
214  nad_append_cdata(nad, username, strlen(username), 3);
215 
216  nad_append_elem(nad, ns, "resource", 2);
217 
218  /* fill out the packet with available auth mechanisms */
219  if(ar_mechs & AR_MECH_TRAD_PLAIN && (sess->host->ar->get_password != NULL || sess->host->ar->check_password != NULL))
220  nad_append_elem(nad, ns, "password", 2);
221 
222  if(ar_mechs & AR_MECH_TRAD_DIGEST && sess->host->ar->get_password != NULL)
223  nad_append_elem(nad, ns, "digest", 2);
224 
225  if (ar_mechs & AR_MECH_TRAD_CRAMMD5 && sess->host->ar->create_challenge != NULL) {
226  err = (sess->host->ar->create_challenge)(sess->host->ar, sess, (char *) username, sess->host->realm,
227  (char *) sess->auth_challenge, sizeof(sess->auth_challenge));
228  if (0 == err) { /* operation failed */
230  return;
231  }
232  else if (1 == err) { /* operation succeeded */
233  nad_append_elem(nad, ns, "crammd5", 2);
234  nad_append_attr(nad, -1, "challenge", sess->auth_challenge);
235  }
236  else ; /* auth method unsupported for user */
237  }
238 
239  /* give it back to the client */
240  sx_nad_write(sess->s, nad);
241 
242  return;
243 }
244 
246 static void _authreg_auth_set(c2s_t c2s, sess_t sess, nad_t nad) {
247  int ns, elem, attr, authd = 0;
248  char username[1024], resource[1024], str[1024], hash[280];
249  int ar_mechs;
250 
251  /* can't auth if they're active */
252  if(sess->active) {
254  return;
255  }
256 
257  ns = nad_find_scoped_namespace(nad, uri_AUTH, NULL);
258 
259  /* sort out the username */
260  elem = nad_find_elem(nad, 1, ns, "username", 1);
261  if(elem < 0)
262  {
263  log_debug(ZONE, "auth set with no username, bouncing it");
264 
266 
267  return;
268  }
269 
270  snprintf(username, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
271  if(stringprep_xmpp_nodeprep(username, 1024) != 0) {
272  log_debug(ZONE, "auth set username failed nodeprep, bouncing it");
274  return;
275  }
276 
277  /* make sure we have the resource */
278  elem = nad_find_elem(nad, 1, ns, "resource", 1);
279  if(elem < 0)
280  {
281  log_debug(ZONE, "auth set with no resource, bouncing it");
282 
284 
285  return;
286  }
287 
288  snprintf(resource, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
289  if(stringprep_xmpp_resourceprep(resource, 1024) != 0) {
290  log_debug(ZONE, "auth set resource failed resourceprep, bouncing it");
292  return;
293  }
294 
295  ar_mechs = c2s->ar_mechanisms;
296  if (sess->s->ssf > 0)
297  ar_mechs = ar_mechs | c2s->ar_ssl_mechanisms;
298 
299  /* no point going on if we have no mechanisms */
302  return;
303  }
304 
305  /* do we have the user? */
306  if((sess->host->ar->user_exists)(sess->host->ar, sess, username, sess->host->realm) == 0) {
308  return;
309  }
310 
311  /* handle CRAM-MD5 response */
312  if(!authd && ar_mechs & AR_MECH_TRAD_CRAMMD5 && sess->host->ar->check_response != NULL)
313  {
314  elem = nad_find_elem(nad, 1, ns, "crammd5", 1);
315  if(elem >= 0)
316  {
317  snprintf(str, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
318  if((sess->host->ar->check_response)(sess->host->ar, sess, username, sess->host->realm, sess->auth_challenge, str) == 0)
319  {
320  log_debug(ZONE, "crammd5 auth (check) succeded");
321  authd = 1;
322  _authreg_auth_log(c2s, sess, "traditional.cram-md5", username, resource, TRUE);
323  } else {
324  _authreg_auth_log(c2s, sess, "traditional.cram-md5", username, resource, FALSE);
325  }
326  }
327  }
328 
329  /* digest auth */
330  if(!authd && ar_mechs & AR_MECH_TRAD_DIGEST && sess->host->ar->get_password != NULL)
331  {
332  elem = nad_find_elem(nad, 1, ns, "digest", 1);
333  if(elem >= 0)
334  {
335  if((sess->host->ar->get_password)(sess->host->ar, sess, username, sess->host->realm, str) == 0)
336  {
337  snprintf(hash, 280, "%s%s", sess->s->id, str);
338  shahash_r(hash, hash);
339 
340  if(strlen(hash) == NAD_CDATA_L(nad, elem) && strncmp(hash, NAD_CDATA(nad, elem), NAD_CDATA_L(nad, elem)) == 0)
341  {
342  log_debug(ZONE, "digest auth succeeded");
343  authd = 1;
344  _authreg_auth_log(c2s, sess, "traditional.digest", username, resource, TRUE);
345  } else {
346  _authreg_auth_log(c2s, sess, "traditional.digest", username, resource, FALSE);
347  }
348  }
349  }
350  }
351 
352  /* plaintext auth (compare) */
353  if(!authd && ar_mechs & AR_MECH_TRAD_PLAIN && sess->host->ar->get_password != NULL)
354  {
355  elem = nad_find_elem(nad, 1, ns, "password", 1);
356  if(elem >= 0)
357  {
358  if((sess->host->ar->get_password)(sess->host->ar, sess, username, sess->host->realm, str) == 0 &&
359  strlen(str) == NAD_CDATA_L(nad, elem) && strncmp(str, NAD_CDATA(nad, elem), NAD_CDATA_L(nad, elem)) == 0)
360  {
361  log_debug(ZONE, "plaintext auth (compare) succeeded");
362  authd = 1;
363  _authreg_auth_log(c2s, sess, "traditional.plain(compare)", username, resource, TRUE);
364  } else {
365  _authreg_auth_log(c2s, sess, "traditional.plain(compare)", username, resource, FALSE);
366  }
367  }
368  }
369 
370  /* plaintext auth (check) */
371  if(!authd && ar_mechs & AR_MECH_TRAD_PLAIN && sess->host->ar->check_password != NULL)
372  {
373  elem = nad_find_elem(nad, 1, ns, "password", 1);
374  if(elem >= 0)
375  {
376  snprintf(str, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
377  if((sess->host->ar->check_password)(sess->host->ar, sess, username, sess->host->realm, str) == 0)
378  {
379  log_debug(ZONE, "plaintext auth (check) succeded");
380  authd = 1;
381  _authreg_auth_log(c2s, sess, "traditional.plain", username, resource, TRUE);
382  } else {
383  _authreg_auth_log(c2s, sess, "traditional.plain", username, resource, FALSE);
384  }
385  }
386  }
387 
388  /* now, are they authenticated? */
389  if(authd)
390  {
391  /* create new bound jid holder */
392  if(sess->resources == NULL) {
393  sess->resources = (bres_t) calloc(1, sizeof(struct bres_st));
394  }
395 
396  /* our local id */
397  sprintf(sess->resources->c2s_id, "%d", sess->s->tag);
398 
399  /* the full user jid for this session */
400  sess->resources->jid = jid_new(sess->s->req_to, -1);
401  jid_reset_components(sess->resources->jid, username, sess->resources->jid->domain, resource);
402 
403  log_write(sess->c2s->log, LOG_NOTICE, "[%d] requesting session: jid=%s", sess->s->tag, jid_full(sess->resources->jid));
404 
405  /* build a result packet, we'll send this back to the client after we have a session for them */
406  sess->result = nad_new();
407 
408  ns = nad_add_namespace(sess->result, uri_CLIENT, NULL);
409 
410  nad_append_elem(sess->result, ns, "iq", 0);
411  nad_set_attr(sess->result, 0, -1, "type", "result", 6);
412 
413  attr = nad_find_attr(nad, 0, -1, "id", NULL);
414  if(attr >= 0)
415  nad_set_attr(sess->result, 0, -1, "id", NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));
416 
417  /* start a session with the sm */
418  sm_start(sess, sess->resources);
419 
420  /* finished with the nad */
421  nad_free(nad);
422 
423  return;
424  }
425 
426  _authreg_auth_log(c2s, sess, "traditional", username, resource, FALSE);
427 
428  /* auth failed, so error */
430 
431  return;
432 }
433 
435 static void _authreg_register_get(c2s_t c2s, sess_t sess, nad_t nad) {
436  int attr, ns;
437  char id[128];
438 
439  /* registrations can happen if reg is enabled and we can create users and set passwords */
440  if(sess->active || !(sess->host->ar->set_password != NULL && sess->host->ar->create_user != NULL &&
441  (sess->host->ar_register_enable || sess->host->ar_register_oob))) {
442 
444  return;
445  }
446 
447  /* extract the id */
448  attr = nad_find_attr(nad, 0, -1, "id", NULL);
449  if(attr >= 0)
450  snprintf(id, 128, "%.*s", NAD_AVAL_L(nad, attr), NAD_AVAL(nad, attr));
451 
452  nad_free(nad);
453 
454  /* build a result packet */
455  nad = nad_new();
456 
457  ns = nad_add_namespace(nad, uri_CLIENT, NULL);
458 
459  nad_append_elem(nad, ns, "iq", 0);
460  nad_append_attr(nad, -1, "type", "result");
461 
462  if(attr >= 0)
463  nad_append_attr(nad, -1, "id", id);
464 
465  ns = nad_add_namespace(nad, uri_REGISTER, NULL);
466  nad_append_elem(nad, ns, "query", 1);
467 
468  nad_append_elem(nad, ns, "instructions", 2);
470 
471  if(sess->host->ar_register_enable) {
472  nad_append_elem(nad, ns, "username", 2);
473  nad_append_elem(nad, ns, "password", 2);
474  }
475 
476  if(sess->host->ar_register_oob) {
477  int ns = nad_add_namespace(nad, uri_OOB, NULL);
478  nad_append_elem(nad, ns, "x", 2);
479  nad_append_elem(nad, ns, "url", 3);
480  nad_append_cdata(nad, sess->host->ar_register_oob, strlen(sess->host->ar_register_oob), 4);
481  }
482 
483  /* give it back to the client */
484  sx_nad_write(sess->s, nad);
485 }
486 
488 static void _authreg_register_set(c2s_t c2s, sess_t sess, nad_t nad)
489 {
490  int ns = 0, elem, attr;
491  char username[1024], password[1024];
492 
493  /* if we're not configured for registration (or pw changes), or we can't set passwords, fail outright */
494  if(!(sess->host->ar_register_enable || sess->host->ar_register_password) || sess->host->ar->set_password == NULL) {
496  return;
497  }
498 
499  ns = nad_find_scoped_namespace(nad, uri_REGISTER, NULL);
500 
501  /* removals */
502  if(sess->active && nad_find_elem(nad, 1, ns, "remove", 1) >= 0) {
503  /* only if full reg is enabled */
504  if(!sess->host->ar_register_enable) {
506  return;
507  }
508 
509  log_debug(ZONE, "user remove requested");
510 
511  /* make sure we can delete them */
512  if(sess->host->ar->delete_user == NULL) {
514  return;
515  }
516 
517  /* otherwise, delete them */
518  if((sess->host->ar->delete_user)(sess->host->ar, sess, sess->resources->jid->node, sess->host->realm) != 0) {
519  log_debug(ZONE, "user delete failed");
521  return;
522  }
523 
524  log_write(c2s->log, LOG_NOTICE, "[%d] deleted user: user=%s; realm=%s", sess->s->tag, sess->resources->jid->node, sess->host->realm);
525 
526  log_write(c2s->log, LOG_NOTICE, "[%d] registration remove succeeded, requesting user deletion: jid=%s", sess->s->tag, jid_user(sess->resources->jid));
527 
528  /* make a result nad */
529  sess->result = nad_new();
530 
531  ns = nad_add_namespace(sess->result, uri_CLIENT, NULL);
532 
533  nad_append_elem(sess->result, ns, "iq", 0);
534  nad_set_attr(sess->result, 0, -1, "type", "result", 6);
535 
536  /* extract the id */
537  attr = nad_find_attr(nad, 0, -1, "id", NULL);
538  if(attr >= 0)
539  nad_set_attr(sess->result, 0, -1, "id", NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));
540 
541  nad_free(nad);
542 
543  sx_nad_write(sess->s, sess->result);
544  sess->result = NULL;
545 
546  /* get the sm to delete them (it will force their sessions to end) */
547  sm_delete(sess, sess->resources);
548 
549  return;
550  }
551 
552  /* username is required */
553  elem = nad_find_elem(nad, 1, ns, "username", 1);
554  if(elem < 0)
555  {
556  log_debug(ZONE, "register set with no username, bouncing it");
558  return;
559  }
560 
561  snprintf(username, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
562  if(stringprep_xmpp_nodeprep(username, 1024) != 0) {
563  log_debug(ZONE, "register set username failed nodeprep, bouncing it");
565  return;
566  }
567 
568  elem = nad_find_elem(nad, 1, ns, "password", 1);
569  if(elem < 0)
570  {
571  log_debug(ZONE, "register set with no password, bouncing it");
573  return;
574  }
575 
576  /* if they're already auth'd, its a password change */
577  if(sess->active)
578  {
579  /* confirm that the username matches their auth id */
580  if(strcmp(username, sess->resources->jid->node) != 0)
581  {
582  log_debug(ZONE, "%s is trying to change password for %s, bouncing it", jid_full(sess->resources->jid), username);
584  return;
585  }
586  }
587 
588  /* can't go on if we're not doing full reg */
589  else if(!sess->host->ar_register_enable) {
591  return;
592  }
593 
594  /* if they exist, bounce */
595  else if((sess->host->ar->user_exists)(sess->host->ar, sess, username, sess->host->realm))
596  {
597  log_debug(ZONE, "attempt to register %s, but they already exist", username);
599  return;
600  }
601 
602  /* make sure we can create them */
603  else if(sess->host->ar->create_user == NULL)
604  {
606  return;
607  }
608 
609  /* otherwise, create them */
610  else if((sess->host->ar->create_user)(sess->host->ar, sess, username, sess->host->realm) != 0)
611  {
612  log_debug(ZONE, "user create failed");
614  return;
615  }
616 
617  else
618  log_write(c2s->log, LOG_NOTICE, "[%d] created user: user=%s; realm=%s", sess->s->tag, username, sess->host->realm);
619 
620  /* extract the password */
621  snprintf(password, 257, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
622 
623  /* change it */
624  if((sess->host->ar->set_password)(sess->host->ar, sess, username, sess->host->realm, password) != 0)
625  {
626  log_debug(ZONE, "password store failed");
628  return;
629  }
630 
631  log_debug(ZONE, "updated auth creds for %s", username);
632 
633  /* make a result nad */
634  sess->result = nad_new();
635 
636  ns = nad_add_namespace(sess->result, uri_CLIENT, NULL);
637 
638  nad_append_elem(sess->result, ns, "iq", 0);
639  nad_set_attr(sess->result, 0, -1, "type", "result", 6);
640 
641  /* extract the id */
642  attr = nad_find_attr(nad, 0, -1, "id", NULL);
643  if(attr >= 0)
644  nad_set_attr(sess->result, 0, -1, "id", NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));
645 
646  /* if they're active, then this was just a password change, and we're done */
647  if(sess->active) {
648  log_write(c2s->log, LOG_NOTICE, "[%d] password changed: jid=%s", sess->s->tag, jid_user(sess->resources->jid));
649  sx_nad_write(sess->s, sess->result);
650  sess->result = NULL;
651  return;
652  }
653 
654  /* create new bound jid holder */
655  if(sess->resources == NULL) {
656  sess->resources = (bres_t) calloc(1, sizeof(struct bres_st));
657  }
658 
659  /* our local id */
660  sprintf(sess->resources->c2s_id, "%d", sess->s->tag);
661 
662  /* the user jid for this transaction */
663  sess->resources->jid = jid_new(sess->s->req_to, -1);
664  jid_reset_components(sess->resources->jid, username, sess->resources->jid->domain, sess->resources->jid->resource);
665 
666  log_write(c2s->log, LOG_NOTICE, "[%d] registration succeeded, requesting user creation: jid=%s", sess->s->tag, jid_user(sess->resources->jid));
667 
668  /* get the sm to create them */
669  sm_create(sess, sess->resources);
670 
671  nad_free(nad);
672 
673  return;
674 }
675 
681  int ns, query, type, authreg = -1, getset = -1;
682 
683  /* need iq */
684  if(NAD_ENAME_L(nad, 0) != 2 || strncmp("iq", NAD_ENAME(nad, 0), 2) != 0)
685  return 1;
686 
687  /* only want auth or register packets */
688  if((ns = nad_find_scoped_namespace(nad, uri_AUTH, NULL)) >= 0 && (query = nad_find_elem(nad, 0, ns, "query", 1)) >= 0)
689  authreg = 0;
690  else if((ns = nad_find_scoped_namespace(nad, uri_REGISTER, NULL)) >= 0 && (query = nad_find_elem(nad, 0, ns, "query", 1)) >= 0)
691  authreg = 1;
692  else
693  return 1;
694 
695  /* if its to someone else, pass it */
696  if(nad_find_attr(nad, 0, -1, "to", NULL) >= 0 && nad_find_attr(nad, 0, -1, "to", sess->s->req_to) < 0)
697  return 1;
698 
699  /* need a type */
700  if((type = nad_find_attr(nad, 0, -1, "type", NULL)) < 0 || NAD_AVAL_L(nad, type) != 3)
701  {
703  return 0;
704  }
705 
706  /* get or set? */
707  if(strncmp("get", NAD_AVAL(nad, type), NAD_AVAL_L(nad, type)) == 0)
708  getset = 0;
709  else if(strncmp("set", NAD_AVAL(nad, type), NAD_AVAL_L(nad, type)) == 0)
710  getset = 1;
711  else
712  {
714  return 0;
715  }
716 
717  /* hand to the correct handler */
718  if(authreg == 0) {
719  /* can't do iq:auth after sasl auth */
720  if(sess->sasl_authd) {
722  return 0;
723  }
724 
725  if(getset == 0) {
726  log_debug(ZONE, "auth get");
727  _authreg_auth_get(c2s, sess, nad);
728  } else if(getset == 1) {
729  log_debug(ZONE, "auth set");
730  _authreg_auth_set(c2s, sess, nad);
731  }
732  }
733 
734  if(authreg == 1) {
735  if(getset == 0) {
736  log_debug(ZONE, "register get");
737  _authreg_register_get(c2s, sess, nad);
738  } else if(getset == 1) {
739  log_debug(ZONE, "register set");
740  _authreg_register_set(c2s, sess, nad);
741  }
742  }
743 
744  /* handled */
745  return 0;
746 }
int(* check_password)(authreg_t ar, sess_t sess, const char *username, const char *realm, char password[257])
check the given password against the stored password, 0 if equal, !0 if not equal (password auth) ...
Definition: c2s.h:354
const char * ip
Definition: sx.h:262
C2S_API void sm_create(sess_t sess, bres_t res)
Definition: sm.c:76
struct bres_st * bres_t
Definition: c2s.h:54
bres_t resources
Definition: c2s.h:103
Definition: nad.h:93
nad_t nad_new(void)
create a new nad
Definition: nad.c:125
int nad_append_attr(nad_t nad, int ns, const char *name, const char *val)
attach new attr to the last elem
Definition: nad.c:745
config_t config
config
Definition: c2s.h:193
#define NAD_CDATA_L(N, E)
Definition: nad.h:186
#define sx_nad_write(s, nad)
Definition: sx.h:167
xht ar_modules
loaded auth/reg modules
Definition: c2s.h:269
#define stanza_err_JID_MALFORMED
Definition: util.h:374
int ar_register_enable
registration
Definition: c2s.h:151
c2s_t c2s
Definition: c2s.h:338
const char * jid_user(jid_t jid)
expand and return the user
Definition: jid.c:338
const char * req_to
Definition: sx.h:282
const char * jid_full(jid_t jid)
expand and return the full
Definition: jid.c:346
jid_t jid_new(const char *id, int len)
make a new jid
Definition: jid.c:81
int nad_find_attr(nad_t nad, unsigned int elem, int ns, const char *name, const char *val)
get a matching attr on this elem, both name and optional val
Definition: nad.c:237
int(* get_password)(authreg_t ar, sess_t sess, const char *username, const char *realm, char password[257])
return this users cleartext password in the array (digest auth, password auth)
Definition: c2s.h:351
#define uri_AUTH
Definition: uri.h:61
int(* create_challenge)(authreg_t ar, sess_t sess, const char *username, const char *realm, char *challenge, int maxlen)
Apple extensions for challenge/response authentication methods.
Definition: c2s.h:375
void nad_set_attr(nad_t nad, unsigned int elem, int ns, const char *name, const char *val, int vallen)
create, update, or zap any matching attr on this elem
Definition: nad.c:407
void nad_append_cdata(nad_t nad, const char *cdata, int len, int depth)
append new cdata to the last elem
Definition: nad.c:753
int(* user_exists)(authreg_t ar, sess_t sess, const char *username, const char *realm)
returns 1 if the user exists, 0 if not
Definition: c2s.h:348
static void _authreg_auth_log(c2s_t c2s, sess_t sess, const char *method, const char *username, const char *resource, int success)
auth logger
Definition: authreg.c:137
void log_write(log_t log, int level, const char *msgfmt,...)
Definition: log.c:104
int(* ar_module_init_fn)(authreg_t)
type for the module init function
Definition: c2s.h:386
#define AR_MECH_TRAD_DIGEST
Definition: c2s.h:121
static void _authreg_auth_set(c2s_t c2s, sess_t sess, nad_t nad)
auth set handler
Definition: authreg.c:246
void shahash_r(const char *str, char hashbuf[41])
convenience (originally by Thomas Muldowney)
Definition: str.c:358
int tag
Definition: sx.h:258
list of resources bound to session
Definition: c2s.h:59
int nad_add_namespace(nad_t nad, const char *uri, const char *prefix)
bring a new namespace into scope
Definition: nad.c:778
nad_t result
Definition: c2s.h:108
int ar_mechanisms
allowed mechanisms
Definition: c2s.h:272
#define stanza_err_CONFLICT
Definition: util.h:368
#define stanza_err_FORBIDDEN
Definition: util.h:370
#define NAD_ENAME(N, E)
Definition: nad.h:183
int initialized
loaded module handle
Definition: c2s.h:339
char * resource
Definition: jid.h:46
struct _authreg_error_st * authreg_error_t
int nad_append_elem(nad_t nad, int ns, const char *name, int depth)
create a new elem on the list
Definition: nad.c:711
void nad_free(nad_t nad)
free that nad
Definition: nad.c:180
int(* set_password)(authreg_t ar, sess_t sess, const char *username, const char *realm, char password[257])
store this password (register)
Definition: c2s.h:357
#define AR_MECH_TRAD_CRAMMD5
Definition: c2s.h:122
jid_t jid
full bound jid
Definition: c2s.h:61
#define AR_MECH_TRAD_PLAIN
Definition: c2s.h:120
sx_t s
Definition: c2s.h:86
#define PATH_MAX
Definition: util.h:69
int authreg_process(c2s_t c2s, sess_t sess, nad_t nad)
processor for iq:auth and iq:register packets return 0 if handled, 1 if not handled ...
Definition: authreg.c:680
jid_t jid_reset_components(jid_t jid, const char *node, const char *domain, const char *resource)
build a jid from components
Definition: jid.c:281
const char * ar_register_instructions
Definition: c2s.h:152
void * pmalloco(pool_t p, int size)
easy safety utility (for creating blank mem for structs, etc)
Definition: pool.c:183
#define NAD_ENAME_L(N, E)
Definition: nad.h:184
const char * realm
our realm (SASL)
Definition: c2s.h:126
void xhash_put(xht h, const char *key, void *val)
Definition: xhash.c:163
int ar_register_password
Definition: c2s.h:154
authreg_t ar
Definition: c2s.h:148
#define stanza_err_BAD_REQUEST
Definition: util.h:367
char * domain
Definition: jid.h:45
host_t host
host this session belongs to
Definition: c2s.h:89
nad_t stanza_tofrom(nad_t nad, int elem)
flip the to and from attributes on this elem
Definition: stanza.c:78
#define uri_REGISTER
Definition: uri.h:62
#define NAD_AVAL_L(N, A)
Definition: nad.h:190
struct authreg_st * authreg_t
Definition: c2s.h:56
#define log_debug(...)
Definition: log.h:65
#define stanza_err_NOT_ALLOWED
Definition: util.h:376
char c2s_id[44]
session id for this jid for us and them
Definition: c2s.h:63
nad_t stanza_error(nad_t nad, int elem, int err)
error the packet
Definition: stanza.c:52
#define uri_CLIENT
Definition: uri.h:35
#define NAD_AVAL(N, A)
Definition: nad.h:189
Definition: c2s.h:157
C2S_API void sm_start(sess_t sess, bres_t res)
Definition: sm.c:66
static void _authreg_register_get(c2s_t c2s, sess_t sess, nad_t nad)
register get handler
Definition: authreg.c:435
There is one instance of this struct per user who is logged in to this c2s instance.
Definition: c2s.h:74
int ssf
Definition: sx.h:343
int nad_find_elem(nad_t nad, unsigned int elem, int ns, const char *name, int depth)
locate the next elem at a given depth with an optional matching name
Definition: nad.c:206
static void _authreg_register_set(c2s_t c2s, sess_t sess, nad_t nad)
register set handler
Definition: authreg.c:488
int(* create_user)(authreg_t ar, sess_t sess, const char *username, const char *realm)
make or break the user (register / register remove)
Definition: c2s.h:360
pool_t xhash_pool(xht h)
get our pool
Definition: xhash.c:305
#define NAD_CDATA(N, E)
Definition: nad.h:185
char auth_challenge[65]
Apple: session challenge for challenge-response authentication.
Definition: c2s.h:113
void * xhash_get(xht h, const char *key)
Definition: xhash.c:184
void authreg_free(authreg_t ar)
shutdown the authreg system
Definition: authreg.c:130
int port
Definition: sx.h:266
#define ZONE
Definition: mio_impl.h:76
void * handle
Definition: c2s.h:342
const char * config_get_one(config_t c, const char *key, int num)
get config value n for this key
Definition: config.c:278
const char * ar_register_oob
Definition: c2s.h:153
#define uri_OOB
Definition: uri.h:56
c2s_t c2s
Definition: c2s.h:75
static void _authreg_auth_get(c2s_t c2s, sess_t sess, nad_t nad)
auth get handler
Definition: authreg.c:146
#define stanza_err_OLD_UNAUTH
Definition: util.h:388
log_t log
logging
Definition: c2s.h:196
int(* check_response)(authreg_t ar, sess_t sess, const char *username, const char *realm, const char *challenge, const char *response)
Definition: c2s.h:376
authreg_t authreg_init(c2s_t c2s, const char *name)
get a handle for the named module
Definition: authreg.c:40
int ar_ssl_mechanisms
Definition: c2s.h:273
const char * id
Definition: sx.h:292
#define stanza_err_INTERNAL_SERVER_ERROR
Definition: util.h:372
int sasl_authd
Definition: c2s.h:110
int active
Definition: c2s.h:105
char * node
Definition: jid.h:44
void(* free)(authreg_t ar)
called prior to authreg shutdown
Definition: c2s.h:367
C2S_API void sm_delete(sess_t sess, bres_t res)
Definition: sm.c:82
int(* delete_user)(authreg_t ar, sess_t sess, const char *username, const char *realm)
Definition: c2s.h:361
int nad_find_scoped_namespace(nad_t nad, const char *uri, const char *prefix)
find a namespace in scope
Definition: nad.c:292
char * _sx_flags(sx_t s)
show sx flags as string - for logging
Definition: sx.c:349