Logo Search packages:      
Sourcecode: jabberd14 version File versions  Download package

static mreturn _mod_register_server_register ( mapi  m  )  [static]

handle jabber:iq:register queries from existing users (removing accounts and changing passwords)

This function ignores all stanzas but iq stanzas.

This module only handles queries in the jabber:iq:register namespace for existing users. Requests are not handled if the <register> element does not exist in the session manager configuration.

This handles querying for the existing registration by the user, changing the password and removing the account.

Parameters:
m the mapi structure
Returns:
M_IGNORE if stanza is not of type iq, M_PASS if stanza has not been handled, M_HANDLED if stanza has been handled

Definition at line 344 of file mod_register.cc.

References udata_struct::id, j_strcmp(), jpacket_reset(), jpacket_subtype(), js_bounce_xmpp(), js_config(), js_deliver(), js_user_delete(), jutil_delay(), jutil_iqresult(), jutil_tofrom(), log_notice(), M_HANDLED, M_PASS, mod_register_check(), mod_register_passwordchange(), xmlnode_list_item_t::next, xmlnode_list_item_t::node, mapi_struct::packet, register_config(), mapi_struct::s, mapi_struct::si, jsmi_struct::std_namespace_prefixes, mapi_struct::user, jsmi_struct::xc, xdb_get(), xdb_set(), xhash_free(), xhash_new(), xhash_put(), xmlnode_free(), xmlnode_get_data(), xmlnode_get_firstchild(), xmlnode_get_lang(), xmlnode_get_list_item(), xmlnode_get_localname(), xmlnode_get_tags(), xmlnode_hide(), xmlnode_insert_cdata(), xmlnode_insert_node(), xmlnode_insert_tag_ns(), xmlnode_put_attrib_ns(), and xmlnode_serialize_string().

Referenced by _mod_register_iq_server().

                                                     {
    xmlnode reg, cur, check;
    xht register_namespace = NULL;
    xmlnode register_config = NULL;
    xmlnode_list_item iter = NULL;

    /* pre-requisites */
    if (m->user == NULL)
      return M_PASS;

    log_debug2(ZONE, LOGT_AUTH, "updating server: %s, user %s", m->user->id->server, jid_full(m->user->id));

    /* check for their registration */
    reg =  xdb_get(m->si->xc, m->user->id, NS_REGISTER);

    log_debug2(ZONE, LOGT_AUTH, "current registration data: %s", xmlnode_serialize_string(reg, xmppd::ns_decl_list(), 0));

    switch (jpacket_subtype(m->packet)) {
      case JPACKET__GET:
          /* create reply to the get */
          xmlnode_put_attrib_ns(m->packet->x, "type", NULL, NULL, "result");
          jutil_tofrom(m->packet->x);

          /* copy in the currently known data */
          xmlnode_insert_node(m->packet->iq, xmlnode_get_firstchild(reg));

          /* add the registered flag */
          xmlnode_insert_tag_ns(m->packet->iq, "registered", NULL, NS_REGISTER);

          /* copy additional required fields from configuration */
          register_config = js_config(m->si, "register:register", NULL);
          register_namespace = xhash_new(1);
          xhash_put(register_namespace, "", const_cast<char*>(NS_REGISTER));
          for (iter = xmlnode_get_tags(register_config, "register:*", m->si->std_namespace_prefixes); iter != NULL; iter = iter->next) {
            if (j_strcmp(xmlnode_get_localname(iter->node), "instructions") == 0)
                continue;

            /* check if the field is already present */
            if (xmlnode_get_tags(m->packet->iq, xmlnode_get_localname(iter->node), register_namespace) != NULL)
                continue;

            /* insert the field */
            xmlnode_insert_tag_ns(m->packet->iq, xmlnode_get_localname(iter->node), NULL, NS_REGISTER);
          }

          /* free temp data */
          xhash_free(register_namespace);
          register_namespace = NULL;
          xmlnode_free(register_config);
          register_config = NULL;

          break;

      case JPACKET__SET:
          if (xmlnode_get_list_item(xmlnode_get_tags(m->packet->iq, "register:remove", m->si->std_namespace_prefixes), 0) != NULL) {
            xmlnode roster, cur;
            xmlnode nounregister = NULL;

            /* is deleting accounts forbidden by the configuration? */
            nounregister = js_config(m->si, "jsm:nounregister", xmlnode_get_lang(m->packet->x));
            if (nounregister != NULL) {
                xterror err = {405, N_("Not Allowed"), "cancel", "not-allowed"};
                char* nounregister_data = xmlnode_get_data(nounregister);
                if (nounregister_data != NULL) {
                  snprintf(err.msg, sizeof(err.msg), "%s", nounregister_data);
                }
                js_bounce_xmpp(m->si, m->s, m->packet->x, err);
                xmlnode_free(nounregister);
                xmlnode_free(reg);
                log_notice(m->user->id->server, "Denied unregistration to user %s", jid_full(m->user->id));
                return M_HANDLED;
            }
          
            log_notice(m->user->id->server,"User Unregistered: %s",m->user->id->user);

            /* let the modules remove their data for this user */
            js_user_delete(m->si, m->user->id);
          } else {
            int only_passwordchange = 1;
            int is_passwordchange = 0;
            int has_username = 0;
            xmlnode_list_item iter = NULL;
            xmlnode noregistrationchange = NULL;

            /* is it a password change, or an update for the registration data? */
            for (iter = xmlnode_get_tags(m->packet->iq, "register:*", m->si->std_namespace_prefixes); iter != NULL; iter = iter->next) {
                const char* localname = xmlnode_get_localname(iter->node);

                /* the username cannot be changed, if it is present, it has to stay the same */
                if (j_strcmp(localname, "username") == 0) {
                  has_username++;
                  jid username_jid = jid_new(m->packet->p, jid_full(m->user->id));
                  jid_set(username_jid, xmlnode_get_data(iter->node), JID_USER);
                  if (jid_cmp(m->user->id, username_jid) == 0) {
                      xmlnode_hide(iter->node); /* we'll regenerate using preped version */
                      continue; /* it's still the same username, everything is perfect */
                  }

                  /* user tries to change his username */
                  js_bounce_xmpp(m->si, m->s, m->packet->x, XTERROR_NOTACCEPTABLE);
                  xmlnode_free(reg);
                  log_notice(m->user->id->server, "Denied update of username for %s to %s", jid_full(m->user->id), xmlnode_get_data(iter->node));
                  return M_HANDLED;
                }

                /* does the request contain a new password? */
                if (j_strcmp(localname, "password") == 0) {
                  is_passwordchange = 1;
                  continue;
                }

                /* anything else is a change in the registration data */
                only_passwordchange = 0;
            }

            /* ensure, that there is exactly one username */
            if (has_username > 1) {
                js_bounce_xmpp(m->si, m->s, m->packet->x, XTERROR_BAD);
                xmlnode_free(reg);
                log_notice(m->user->id->server, "User %s sent registration data set request containing multiple usernames", jid_full(m->user->id));
                return M_HANDLED;
            }
            xmlnode_insert_cdata(xmlnode_insert_tag_ns(m->packet->iq, "username", NULL, NS_REGISTER), m->user->id->user, -1);

            /* did we find anything useful? */
            if (!is_passwordchange && only_passwordchange) {
                js_bounce_xmpp(m->si, m->s, m->packet->x, XTERROR_BAD);
                xmlnode_free(reg);
                log_notice(m->user->id->server, "User %s sent incomplete registration data set request", jid_full(m->user->id));
                return M_HANDLED;
            }

            /* if it is a real regstration update (not only password-change), check that all required fields have been provided */
            if (!only_passwordchange) {
                log_debug2(ZONE, LOGT_ROSTER, "updating registration for %s",jid_full(m->user->id));

                if (mod_register_check(m, NULL) == M_HANDLED) {
                  js_deliver(m->si, jpacket_reset(m->packet), m->s);
                  xmlnode_free(reg);
                  return M_HANDLED;
                }

                /* is updating registration data forbidden by the configuration? */
                noregistrationchange = js_config(m->si, "jsm:noregistrationchange", xmlnode_get_lang(m->packet->x));
                if (noregistrationchange != NULL) {
                  xterror err = {405, N_("Not Allowed"), "cancel", "not-allowed"};
                  char* noregistrationchange_data = xmlnode_get_data(noregistrationchange);
                  if (noregistrationchange_data != NULL) {
                      snprintf(err.msg, sizeof(err.msg), "%s", noregistrationchange_data);
                  }
                  js_bounce_xmpp(m->si, m->s, m->packet->x, err);
                  xmlnode_free(noregistrationchange);
                  xmlnode_free(reg);
                  log_notice(m->user->id->server, "Denied registration data change to user %s", jid_full(m->user->id));
                  return M_HANDLED;
                }
            }

            /* let the authentication modules update the stored password */
            if (is_passwordchange) {
                xmlnode nopasswordchange = js_config(m->si, "jsm:nopasswordchange", xmlnode_get_lang(m->packet->x));
                if (nopasswordchange != NULL) {
                  xterror err = {405, N_("Not Allowed"), "cancel", "not-allowed"};
                  char* nopasswordchange_data = xmlnode_get_data(nopasswordchange);
                  if (nopasswordchange_data != NULL) {
                      snprintf(err.msg, sizeof(err.msg), "%s", nopasswordchange_data);
                  }
                  js_bounce_xmpp(m->si, m->s, m->packet->x, err);
                  xmlnode_free(nopasswordchange);
                  xmlnode_free(reg);
                  log_notice(m->user->id->server, "Denied password change to user %s", jid_full(m->user->id));
                  return M_HANDLED;
                }
                xmlnode_free(nopasswordchange);

                if (mod_register_passwordchange(m) == M_HANDLED) {
                  xmlnode_free(reg);
                  return M_HANDLED;
                }
                log_notice(m->user->id->server, "User %s changed password", jid_full(m->user->id));
            }

            if (!only_passwordchange) {
                /* update the registration data */
                xmlnode_hide(xmlnode_get_list_item(xmlnode_get_tags(m->packet->iq, "register:username", m->si->std_namespace_prefixes), 0)); /* hide the username/password from the reg db */
                xmlnode_hide(xmlnode_get_list_item(xmlnode_get_tags(m->packet->iq, "register:password", m->si->std_namespace_prefixes), 0));
                jutil_delay(m->packet->iq,"updated");
                xdb_set(m->si->xc, m->user->id, NS_REGISTER, m->packet->iq);
            }
          }
          /* clean up and respond */
          jutil_iqresult(m->packet->x);
          break;

      default:
          xmlnode_free(reg);
          return M_PASS;
    }

    xmlnode_free(reg);
    js_deliver(m->si, jpacket_reset(m->packet), m->s);
    return M_HANDLED;
}


Generated by  Doxygen 1.6.0   Back to index