jabberd2  2.3.3
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  /* load authreg module */
48  modules_path = config_get_one(c2s->config, "authreg.path", 0);
49  if (modules_path != NULL)
50  log_write(c2s->log, LOG_NOTICE, "modules search path: %s", modules_path);
51  else
52  log_write(c2s->log, LOG_NOTICE, "modules search path undefined, using default: "LIBRARY_DIR);
53 
54  log_write(c2s->log, LOG_INFO, "loading '%s' authreg module", name);
55 #ifndef _WIN32
56  if (modules_path != NULL)
57  snprintf(mod_fullpath, PATH_MAX, "%s/authreg_%s.so", modules_path, name);
58  else
59  snprintf(mod_fullpath, PATH_MAX, "%s/authreg_%s.so", LIBRARY_DIR, name);
60  handle = dlopen(mod_fullpath, RTLD_LAZY);
61  if (handle != NULL)
62  init_fn = dlsym(handle, "ar_init");
63 #else
64  if (modules_path != NULL)
65  snprintf(mod_fullpath, PATH_MAX, "%s\\authreg_%s.dll", modules_path, name);
66  else
67  snprintf(mod_fullpath, PATH_MAX, "authreg_%s.dll", name);
68  handle = (void*) LoadLibrary(mod_fullpath);
69  if (handle != NULL)
70  init_fn = (ar_module_init_fn)GetProcAddress((HMODULE) handle, "ar_init");
71 #endif
72 
73  if (handle != NULL && init_fn != NULL) {
74  log_debug(ZONE, "preloaded module '%s' (not initialized yet)", name);
75  } else {
76 #ifndef _WIN32
77  log_write(c2s->log, LOG_ERR, "failed loading authreg module '%s' (%s)", name, dlerror());
78  if (handle != NULL)
79  dlclose(handle);
80 #else
81  log_write(c2s->log, LOG_ERR, "failed loading authreg module '%s' (errcode: %x)", name, GetLastError());
82  if (handle != NULL)
83  FreeLibrary((HMODULE) handle);
84 #endif
85  return NULL;
86  }
87 
88  /* make a new one */
89  ar = (authreg_t) calloc(1, sizeof(struct authreg_st));
90 
91  ar->c2s = c2s;
92 
93  /* call the initialiser */
94  if((init_fn)(ar) != 0)
95  {
96  log_write(c2s->log, LOG_ERR, "failed to initialize auth module '%s'", name);
97  authreg_free(ar);
98  return NULL;
99  }
100 
101  /* we need user_exists(), at the very least */
102  if(ar->user_exists == NULL)
103  {
104  log_write(c2s->log, LOG_ERR, "auth module '%s' has no check for user existence", name);
105  authreg_free(ar);
106  return NULL;
107  }
108 
109  /* its good */
110  log_write(c2s->log, LOG_NOTICE, "initialized auth module '%s'", name);
111 
112  return ar;
113 }
114 
117  if (ar) {
118  if(ar->free != NULL) (ar->free)(ar);
119  free(ar);
120  }
121 }
122 
124 inline static void _authreg_auth_log(c2s_t c2s, sess_t sess, const char *method, const char *username, const char *resource, int success) {
125  log_write(c2s->log, LOG_NOTICE, "[%d] %s authentication %s: %s@%s/%s %s:%d%s%s",
126  sess->s->tag, method, success ? "succeeded" : "failed",
127  username, sess->host->realm, resource,
128  sess->s->ip, sess->s->port,
129  sess->s->ssf ? " TLS" : "", sess->s->compressed ? " ZLIB" : ""
130  );
131 }
132 
134 static void _authreg_auth_get(c2s_t c2s, sess_t sess, nad_t nad) {
135  int ns, elem, attr, err;
136  char username[1024], id[128];
137  int ar_mechs;
138 
139  /* can't auth if they're active */
140  if(sess->active) {
142  return;
143  }
144 
145  /* sort out the username */
146  ns = nad_find_scoped_namespace(nad, uri_AUTH, NULL);
147  elem = nad_find_elem(nad, 1, ns, "username", 1);
148  if(elem < 0)
149  {
150  log_debug(ZONE, "auth get with no username, bouncing it");
151 
153 
154  return;
155  }
156 
157  snprintf(username, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
158  if(stringprep_xmpp_nodeprep(username, 1024) != 0) {
159  log_debug(ZONE, "auth get username failed nodeprep, bouncing it");
161  return;
162  }
163 
164  ar_mechs = c2s->ar_mechanisms;
165  if (sess->s->ssf>0)
166  ar_mechs = ar_mechs | c2s->ar_ssl_mechanisms;
167 
168  /* no point going on if we have no mechanisms */
171  return;
172  }
173 
174  /* do we have the user? */
175  if((c2s->ar->user_exists)(c2s->ar, sess, username, sess->host->realm) == 0) {
177  return;
178  }
179 
180  /* extract the id */
181  attr = nad_find_attr(nad, 0, -1, "id", NULL);
182  if(attr >= 0)
183  snprintf(id, 128, "%.*s", NAD_AVAL_L(nad, attr), NAD_AVAL(nad, attr));
184 
185  nad_free(nad);
186 
187  /* build a result packet */
188  nad = nad_new();
189 
190  ns = nad_add_namespace(nad, uri_CLIENT, NULL);
191 
192  nad_append_elem(nad, ns, "iq", 0);
193  nad_append_attr(nad, -1, "type", "result");
194 
195  if(attr >= 0)
196  nad_append_attr(nad, -1, "id", id);
197 
198  ns = nad_add_namespace(nad, uri_AUTH, NULL);
199  nad_append_elem(nad, ns, "query", 1);
200 
201  nad_append_elem(nad, ns, "username", 2);
202  nad_append_cdata(nad, username, strlen(username), 3);
203 
204  nad_append_elem(nad, ns, "resource", 2);
205 
206  /* fill out the packet with available auth mechanisms */
207  if(ar_mechs & AR_MECH_TRAD_PLAIN && (c2s->ar->get_password != NULL || c2s->ar->check_password != NULL))
208  nad_append_elem(nad, ns, "password", 2);
209 
210  if(ar_mechs & AR_MECH_TRAD_DIGEST && c2s->ar->get_password != NULL)
211  nad_append_elem(nad, ns, "digest", 2);
212 
213  if (ar_mechs & AR_MECH_TRAD_CRAMMD5 && c2s->ar->create_challenge != NULL) {
214  err = (c2s->ar->create_challenge)(c2s->ar, sess, (char *) username, sess->host->realm,
215  (char *) sess->auth_challenge, sizeof(sess->auth_challenge));
216  if (0 == err) { /* operation failed */
218  return;
219  }
220  else if (1 == err) { /* operation succeeded */
221  nad_append_elem(nad, ns, "crammd5", 2);
222  nad_append_attr(nad, -1, "challenge", sess->auth_challenge);
223  }
224  else ; /* auth method unsupported for user */
225  }
226 
227  /* give it back to the client */
228  sx_nad_write(sess->s, nad);
229 
230  return;
231 }
232 
234 static void _authreg_auth_set(c2s_t c2s, sess_t sess, nad_t nad) {
235  int ns, elem, attr, authd = 0;
236  char username[1024], resource[1024], str[1024], hash[280];
237  int ar_mechs;
238 
239  /* can't auth if they're active */
240  if(sess->active) {
242  return;
243  }
244 
245  ns = nad_find_scoped_namespace(nad, uri_AUTH, NULL);
246 
247  /* sort out the username */
248  elem = nad_find_elem(nad, 1, ns, "username", 1);
249  if(elem < 0)
250  {
251  log_debug(ZONE, "auth set with no username, bouncing it");
252 
254 
255  return;
256  }
257 
258  snprintf(username, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
259  if(stringprep_xmpp_nodeprep(username, 1024) != 0) {
260  log_debug(ZONE, "auth set username failed nodeprep, bouncing it");
262  return;
263  }
264 
265  /* make sure we have the resource */
266  elem = nad_find_elem(nad, 1, ns, "resource", 1);
267  if(elem < 0)
268  {
269  log_debug(ZONE, "auth set with no resource, bouncing it");
270 
272 
273  return;
274  }
275 
276  snprintf(resource, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
277  if(stringprep_xmpp_resourceprep(resource, 1024) != 0) {
278  log_debug(ZONE, "auth set resource failed resourceprep, bouncing it");
280  return;
281  }
282 
283  ar_mechs = c2s->ar_mechanisms;
284  if (sess->s->ssf > 0)
285  ar_mechs = ar_mechs | c2s->ar_ssl_mechanisms;
286 
287  /* no point going on if we have no mechanisms */
290  return;
291  }
292 
293  /* do we have the user? */
294  if((c2s->ar->user_exists)(c2s->ar, sess, username, sess->host->realm) == 0) {
296  return;
297  }
298 
299  /* handle CRAM-MD5 response */
300  if(!authd && ar_mechs & AR_MECH_TRAD_CRAMMD5 && c2s->ar->check_response != NULL)
301  {
302  elem = nad_find_elem(nad, 1, ns, "crammd5", 1);
303  if(elem >= 0)
304  {
305  snprintf(str, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
306  if((c2s->ar->check_response)(c2s->ar, sess, username, sess->host->realm, sess->auth_challenge, str) == 0)
307  {
308  log_debug(ZONE, "crammd5 auth (check) succeded");
309  authd = 1;
310  _authreg_auth_log(c2s, sess, "traditional.cram-md5", username, resource, TRUE);
311  } else {
312  _authreg_auth_log(c2s, sess, "traditional.cram-md5", username, resource, FALSE);
313  }
314  }
315  }
316 
317  /* digest auth */
318  if(!authd && ar_mechs & AR_MECH_TRAD_DIGEST && c2s->ar->get_password != NULL)
319  {
320  elem = nad_find_elem(nad, 1, ns, "digest", 1);
321  if(elem >= 0)
322  {
323  if((c2s->ar->get_password)(c2s->ar, sess, username, sess->host->realm, str) == 0)
324  {
325  snprintf(hash, 280, "%s%s", sess->s->id, str);
326  shahash_r(hash, hash);
327 
328  if(strlen(hash) == NAD_CDATA_L(nad, elem) && strncmp(hash, NAD_CDATA(nad, elem), NAD_CDATA_L(nad, elem)) == 0)
329  {
330  log_debug(ZONE, "digest auth succeeded");
331  authd = 1;
332  _authreg_auth_log(c2s, sess, "traditional.digest", username, resource, TRUE);
333  } else {
334  _authreg_auth_log(c2s, sess, "traditional.digest", username, resource, FALSE);
335  }
336  }
337  }
338  }
339 
340  /* plaintext auth (compare) */
341  if(!authd && ar_mechs & AR_MECH_TRAD_PLAIN && c2s->ar->get_password != NULL)
342  {
343  elem = nad_find_elem(nad, 1, ns, "password", 1);
344  if(elem >= 0)
345  {
346  if((c2s->ar->get_password)(c2s->ar, sess, username, sess->host->realm, str) == 0 &&
347  strlen(str) == NAD_CDATA_L(nad, elem) && strncmp(str, NAD_CDATA(nad, elem), NAD_CDATA_L(nad, elem)) == 0)
348  {
349  log_debug(ZONE, "plaintext auth (compare) succeeded");
350  authd = 1;
351  _authreg_auth_log(c2s, sess, "traditional.plain(compare)", username, resource, TRUE);
352  } else {
353  _authreg_auth_log(c2s, sess, "traditional.plain(compare)", username, resource, FALSE);
354  }
355  }
356  }
357 
358  /* plaintext auth (check) */
359  if(!authd && ar_mechs & AR_MECH_TRAD_PLAIN && c2s->ar->check_password != NULL)
360  {
361  elem = nad_find_elem(nad, 1, ns, "password", 1);
362  if(elem >= 0)
363  {
364  snprintf(str, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
365  if((c2s->ar->check_password)(c2s->ar, sess, username, sess->host->realm, str) == 0)
366  {
367  log_debug(ZONE, "plaintext auth (check) succeded");
368  authd = 1;
369  _authreg_auth_log(c2s, sess, "traditional.plain", username, resource, TRUE);
370  } else {
371  _authreg_auth_log(c2s, sess, "traditional.plain", username, resource, FALSE);
372  }
373  }
374  }
375 
376  /* now, are they authenticated? */
377  if(authd)
378  {
379  /* create new bound jid holder */
380  if(sess->resources == NULL) {
381  sess->resources = (bres_t) calloc(1, sizeof(struct bres_st));
382  }
383 
384  /* our local id */
385  sprintf(sess->resources->c2s_id, "%d", sess->s->tag);
386 
387  /* the full user jid for this session */
388  sess->resources->jid = jid_new(sess->s->req_to, -1);
389  jid_reset_components(sess->resources->jid, username, sess->resources->jid->domain, resource);
390 
391  log_write(sess->c2s->log, LOG_NOTICE, "[%d] requesting session: jid=%s", sess->s->tag, jid_full(sess->resources->jid));
392 
393  /* build a result packet, we'll send this back to the client after we have a session for them */
394  sess->result = nad_new();
395 
396  ns = nad_add_namespace(sess->result, uri_CLIENT, NULL);
397 
398  nad_append_elem(sess->result, ns, "iq", 0);
399  nad_set_attr(sess->result, 0, -1, "type", "result", 6);
400 
401  attr = nad_find_attr(nad, 0, -1, "id", NULL);
402  if(attr >= 0)
403  nad_set_attr(sess->result, 0, -1, "id", NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));
404 
405  /* start a session with the sm */
406  sm_start(sess, sess->resources);
407 
408  /* finished with the nad */
409  nad_free(nad);
410 
411  return;
412  }
413 
414  _authreg_auth_log(c2s, sess, "traditional", username, resource, FALSE);
415 
416  /* auth failed, so error */
418 
419  return;
420 }
421 
423 static void _authreg_register_get(c2s_t c2s, sess_t sess, nad_t nad) {
424  int attr, ns;
425  char id[128];
426 
427  /* registrations can happen if reg is enabled and we can create users and set passwords */
428  if(sess->active || !(c2s->ar->set_password != NULL && c2s->ar->create_user != NULL &&
429  (sess->host->ar_register_enable || sess->host->ar_register_oob))) {
430 
432  return;
433  }
434 
435  /* extract the id */
436  attr = nad_find_attr(nad, 0, -1, "id", NULL);
437  if(attr >= 0)
438  snprintf(id, 128, "%.*s", NAD_AVAL_L(nad, attr), NAD_AVAL(nad, attr));
439 
440  nad_free(nad);
441 
442  /* build a result packet */
443  nad = nad_new();
444 
445  ns = nad_add_namespace(nad, uri_CLIENT, NULL);
446 
447  nad_append_elem(nad, ns, "iq", 0);
448  nad_append_attr(nad, -1, "type", "result");
449 
450  if(attr >= 0)
451  nad_append_attr(nad, -1, "id", id);
452 
453  ns = nad_add_namespace(nad, uri_REGISTER, NULL);
454  nad_append_elem(nad, ns, "query", 1);
455 
456  nad_append_elem(nad, ns, "instructions", 2);
458 
459  if(sess->host->ar_register_enable) {
460  nad_append_elem(nad, ns, "username", 2);
461  nad_append_elem(nad, ns, "password", 2);
462  }
463 
464  if(sess->host->ar_register_oob) {
465  int ns = nad_add_namespace(nad, uri_OOB, NULL);
466  nad_append_elem(nad, ns, "x", 2);
467  nad_append_elem(nad, ns, "url", 3);
468  nad_append_cdata(nad, sess->host->ar_register_oob, strlen(sess->host->ar_register_oob), 4);
469  }
470 
471  /* give it back to the client */
472  sx_nad_write(sess->s, nad);
473 }
474 
476 static void _authreg_register_set(c2s_t c2s, sess_t sess, nad_t nad)
477 {
478  int ns = 0, elem, attr;
479  char username[1024], password[1024];
480 
481  /* if we're not configured for registration (or pw changes), or we can't set passwords, fail outright */
482  if(!(sess->host->ar_register_enable || sess->host->ar_register_password) || c2s->ar->set_password == NULL) {
484  return;
485  }
486 
487  ns = nad_find_scoped_namespace(nad, uri_REGISTER, NULL);
488 
489  /* removals */
490  if(sess->active && nad_find_elem(nad, 1, ns, "remove", 1) >= 0) {
491  /* only if full reg is enabled */
492  if(!sess->host->ar_register_enable) {
494  return;
495  }
496 
497  log_debug(ZONE, "user remove requested");
498 
499  /* make sure we can delete them */
500  if(c2s->ar->delete_user == NULL) {
502  return;
503  }
504 
505  /* otherwise, delete them */
506  if((c2s->ar->delete_user)(c2s->ar, sess, sess->resources->jid->node, sess->host->realm) != 0) {
507  log_debug(ZONE, "user delete failed");
509  return;
510  }
511 
512  log_write(c2s->log, LOG_NOTICE, "[%d] deleted user: user=%s; realm=%s", sess->s->tag, sess->resources->jid->node, sess->host->realm);
513 
514  log_write(c2s->log, LOG_NOTICE, "[%d] registration remove succeeded, requesting user deletion: jid=%s", sess->s->tag, jid_user(sess->resources->jid));
515 
516  /* make a result nad */
517  sess->result = nad_new();
518 
519  ns = nad_add_namespace(sess->result, uri_CLIENT, NULL);
520 
521  nad_append_elem(sess->result, ns, "iq", 0);
522  nad_set_attr(sess->result, 0, -1, "type", "result", 6);
523 
524  /* extract the id */
525  attr = nad_find_attr(nad, 0, -1, "id", NULL);
526  if(attr >= 0)
527  nad_set_attr(sess->result, 0, -1, "id", NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));
528 
529  nad_free(nad);
530 
531  sx_nad_write(sess->s, sess->result);
532  sess->result = NULL;
533 
534  /* get the sm to delete them (it will force their sessions to end) */
535  sm_delete(sess, sess->resources);
536 
537  return;
538  }
539 
540  /* username is required */
541  elem = nad_find_elem(nad, 1, ns, "username", 1);
542  if(elem < 0)
543  {
544  log_debug(ZONE, "register set with no username, bouncing it");
546  return;
547  }
548 
549  snprintf(username, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
550  if(stringprep_xmpp_nodeprep(username, 1024) != 0) {
551  log_debug(ZONE, "register set username failed nodeprep, bouncing it");
553  return;
554  }
555 
556  elem = nad_find_elem(nad, 1, ns, "password", 1);
557  if(elem < 0)
558  {
559  log_debug(ZONE, "register set with no password, bouncing it");
561  return;
562  }
563 
564  /* if they're already auth'd, its a password change */
565  if(sess->active)
566  {
567  /* confirm that the username matches their auth id */
568  if(strcmp(username, sess->resources->jid->node) != 0)
569  {
570  log_debug(ZONE, "%s is trying to change password for %s, bouncing it", jid_full(sess->resources->jid), username);
572  return;
573  }
574  }
575 
576  /* can't go on if we're not doing full reg */
577  else if(!sess->host->ar_register_enable) {
579  return;
580  }
581 
582  /* if they exist, bounce */
583  else if((c2s->ar->user_exists)(c2s->ar, sess, username, sess->host->realm))
584  {
585  log_debug(ZONE, "attempt to register %s, but they already exist", username);
587  return;
588  }
589 
590  /* make sure we can create them */
591  else if(c2s->ar->create_user == NULL)
592  {
594  return;
595  }
596 
597  /* otherwise, create them */
598  else if((c2s->ar->create_user)(c2s->ar, sess, username, sess->host->realm) != 0)
599  {
600  log_debug(ZONE, "user create failed");
602  return;
603  }
604 
605  else
606  log_write(c2s->log, LOG_NOTICE, "[%d] created user: user=%s; realm=%s", sess->s->tag, username, sess->host->realm);
607 
608  /* extract the password */
609  snprintf(password, 257, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
610 
611  /* change it */
612  if((c2s->ar->set_password)(c2s->ar, sess, username, sess->host->realm, password) != 0)
613  {
614  log_debug(ZONE, "password store failed");
616  return;
617  }
618 
619  log_debug(ZONE, "updated auth creds for %s", username);
620 
621  /* make a result nad */
622  sess->result = nad_new();
623 
624  ns = nad_add_namespace(sess->result, uri_CLIENT, NULL);
625 
626  nad_append_elem(sess->result, ns, "iq", 0);
627  nad_set_attr(sess->result, 0, -1, "type", "result", 6);
628 
629  /* extract the id */
630  attr = nad_find_attr(nad, 0, -1, "id", NULL);
631  if(attr >= 0)
632  nad_set_attr(sess->result, 0, -1, "id", NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));
633 
634  /* if they're active, then this was just a password change, and we're done */
635  if(sess->active) {
636  log_write(c2s->log, LOG_NOTICE, "[%d] password changed: jid=%s", sess->s->tag, jid_user(sess->resources->jid));
637  sx_nad_write(sess->s, sess->result);
638  sess->result = NULL;
639  return;
640  }
641 
642  /* create new bound jid holder */
643  if(sess->resources == NULL) {
644  sess->resources = (bres_t) calloc(1, sizeof(struct bres_st));
645  }
646 
647  /* our local id */
648  sprintf(sess->resources->c2s_id, "%d", sess->s->tag);
649 
650  /* the user jid for this transaction */
651  sess->resources->jid = jid_new(sess->s->req_to, -1);
652  jid_reset_components(sess->resources->jid, username, sess->resources->jid->domain, sess->resources->jid->resource);
653 
654  log_write(c2s->log, LOG_NOTICE, "[%d] registration succeeded, requesting user creation: jid=%s", sess->s->tag, jid_user(sess->resources->jid));
655 
656  /* get the sm to create them */
657  sm_create(sess, sess->resources);
658 
659  nad_free(nad);
660 
661  return;
662 }
663 
668 int authreg_process(c2s_t c2s, sess_t sess, nad_t nad) {
669  int ns, query, type, authreg = -1, getset = -1;
670 
671  /* need iq */
672  if(NAD_ENAME_L(nad, 0) != 2 || strncmp("iq", NAD_ENAME(nad, 0), 2) != 0)
673  return 1;
674 
675  /* only want auth or register packets */
676  if((ns = nad_find_scoped_namespace(nad, uri_AUTH, NULL)) >= 0 && (query = nad_find_elem(nad, 0, ns, "query", 1)) >= 0)
677  authreg = 0;
678  else if((ns = nad_find_scoped_namespace(nad, uri_REGISTER, NULL)) >= 0 && (query = nad_find_elem(nad, 0, ns, "query", 1)) >= 0)
679  authreg = 1;
680  else
681  return 1;
682 
683  /* if its to someone else, pass it */
684  if(nad_find_attr(nad, 0, -1, "to", NULL) >= 0 && nad_find_attr(nad, 0, -1, "to", sess->s->req_to) < 0)
685  return 1;
686 
687  /* need a type */
688  if((type = nad_find_attr(nad, 0, -1, "type", NULL)) < 0 || NAD_AVAL_L(nad, type) != 3)
689  {
691  return 0;
692  }
693 
694  /* get or set? */
695  if(strncmp("get", NAD_AVAL(nad, type), NAD_AVAL_L(nad, type)) == 0)
696  getset = 0;
697  else if(strncmp("set", NAD_AVAL(nad, type), NAD_AVAL_L(nad, type)) == 0)
698  getset = 1;
699  else
700  {
702  return 0;
703  }
704 
705  /* hand to the correct handler */
706  if(authreg == 0) {
707  /* can't do iq:auth after sasl auth */
708  if(sess->sasl_authd) {
710  return 0;
711  }
712 
713  if(getset == 0) {
714  log_debug(ZONE, "auth get");
715  _authreg_auth_get(c2s, sess, nad);
716  } else if(getset == 1) {
717  log_debug(ZONE, "auth set");
718  _authreg_auth_set(c2s, sess, nad);
719  }
720  }
721 
722  if(authreg == 1) {
723  if(getset == 0) {
724  log_debug(ZONE, "register get");
725  _authreg_register_get(c2s, sess, nad);
726  } else if(getset == 1) {
727  log_debug(ZONE, "register set");
728  _authreg_register_set(c2s, sess, nad);
729  }
730  }
731 
732  /* handled */
733  return 0;
734 }
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:334
const char * ip
Definition: sx.h:260
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:701
config_t config
config
Definition: c2s.h:186
#define NAD_CDATA_L(N, E)
Definition: nad.h:186
#define sx_nad_write(s, nad)
Definition: sx.h:166
#define stanza_err_JID_MALFORMED
Definition: util.h:374
int ar_register_enable
registration
Definition: c2s.h:144
c2s_t c2s
Definition: c2s.h:322
const char * jid_user(jid_t jid)
expand and return the user
Definition: jid.c:339
const char * req_to
Definition: sx.h:280
const char * jid_full(jid_t jid)
expand and return the full
Definition: jid.c:347
jid_t jid_new(const char *id, int len)
make a new jid
Definition: jid.c:81
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:331
#define uri_AUTH
Definition: uri.h:60
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:355
int nad_find_elem(nad_t nad, 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:204
void nad_append_cdata(nad_t nad, const char *cdata, int len, int depth)
append new cdata to the last elem
Definition: nad.c:709
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:328
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:124
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:366
#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:234
void shahash_r(const char *str, char hashbuf[41])
convenience (originally by Thomas Muldowney)
Definition: str.c:358
int tag
Definition: sx.h:256
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:734
nad_t result
Definition: c2s.h:108
int ar_mechanisms
allowed mechanisms
Definition: c2s.h:256
#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
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:667
void nad_free(nad_t nad)
free that nad
Definition: nad.c:178
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:337
#define AR_MECH_TRAD_CRAMMD5
Definition: c2s.h:122
jid_t jid
full bound jid
Definition: c2s.h:61
authreg_t ar
Definition: c2s.h:253
#define AR_MECH_TRAD_PLAIN
Definition: c2s.h:120
sx_t s
Definition: c2s.h:86
#define PATH_MAX
Definition: util.h:69
void nad_set_attr(nad_t nad, 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:375
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:668
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:145
#define NAD_ENAME_L(N, E)
Definition: nad.h:184
const char * realm
our realm (SASL)
Definition: c2s.h:126
int ar_register_password
Definition: c2s.h:147
int compressed
Definition: sx.h:340
#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:61
#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:151
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:423
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:337
static void _authreg_register_set(c2s_t c2s, sess_t sess, nad_t nad)
register set handler
Definition: authreg.c:476
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:340
#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 authreg_free(authreg_t ar)
shutdown the authreg system
Definition: authreg.c:116
int port
Definition: sx.h:264
#define ZONE
Definition: mio_impl.h:76
const char * config_get_one(config_t c, const char *key, int num)
get config value n for this key
Definition: config.c:277
const char * ar_register_oob
Definition: c2s.h:146
#define uri_OOB
Definition: uri.h:55
int nad_find_attr(nad_t nad, 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:235
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:134
#define stanza_err_OLD_UNAUTH
Definition: util.h:388
log_t log
logging
Definition: c2s.h:189
int(* check_response)(authreg_t ar, sess_t sess, const char *username, const char *realm, const char *challenge, const char *response)
Definition: c2s.h:356
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:257
const char * id
Definition: sx.h:290
#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:347
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:341
int nad_find_scoped_namespace(nad_t nad, const char *uri, const char *prefix)
find a namespace in scope
Definition: nad.c:290