int csa_doresendemail(void *source, int cargc, char **cargv) {
  reguser *rup;
  nick *sender=(nick *)source;

  if(cargc<1) {
    controlreply(sender, "RESENDEMAIL FALSE args");
    return CMD_ERROR;
  }

  rup = findreguserbyID(atoi(cargv[0]));
  if(rup == NULL) {
    controlreply(sender, "RESENDEMAIL FALSE useridnotexist");
    return CMD_ERROR;
  }

  if(!UIsInactive(rup)) {
    controlreply(sender, "RESENDEMAIL FALSE accountactive");
    return CMD_ERROR;
  }

  sendemail(rup);
  controlreply(sender, "RESENDEMAIL TRUE");
  cs_log(sender,"RESENDEMAIL OK username %s",rup->username);

  return CMD_OK;
}
int csa_dosetemail(void *source, int cargc, char **cargv) {
  char *email;
  char *error;
  reguser *rup;
  nick *sender=(nick *)source;

  if(cargc<3) {
    controlreply(sender, "SETEMAIL FALSE args");
    return CMD_ERROR;
  }

  rup = findreguserbyID(atoi(cargv[0]));
  if(rup == NULL) {
    controlreply(sender, "SETEMAIL FALSE useridnotexist");
    return CMD_ERROR;
  }

  if(UHasStaffPriv(rup)) {
    controlreply(sender, "SETEMAIL FALSE privuser");
    return CMD_ERROR;
  }

  if(UHasSuspension(rup)) {
    controlreply(sender, "SETEMAIL FALSE suspended");
    return CMD_ERROR;
  }

  if(rup->lastpasschange > atoi(cargv[1])) {
    controlreply(sender, "SETEMAIL FALSE passwordchanged");
    return CMD_ERROR;
  }

  email = cargv[2];

  if(!strcmp(email, rup->email->content)) {
    /* setting to the same thing? fine! */
    controlreply(sender, "SETEMAIL TRUE");
    return CMD_OK;
  }

  error = email_to_error(email);
  if(error) {
    controlreply(sender, "SETEMAIL FALSE %s", error);
    return CMD_ERROR;
  }

  freesstring(rup->email);
  rup->email=getsstring(email,EMAILLEN);
  cs_log(sender,"SETEMAIL OK username %s email %s",rup->username, rup->email->content);

  csdb_updateuser(rup);
  sendemail(rup);

  controlreply(sender, "SETEMAIL TRUE");

  return CMD_OK;
}
Exemple #3
0
int main()
{
    char email[] = "*****@*****.**";
    char body[] = "From: \"www\"<*****@*****.**>\r\n"
                  "To: \"w111\"<*****@*****.**>\r\n"
                  "Subject: Hello\r\n\r\n"
                  "Hello World, Hello Email!";
    sendemail(email, body);
    return 0;
}
int csa_dosettempemail(void *source, int cargc, char **cargv) {
  char *email;
  char *error;
  reguser *rup;
  nick *sender=(nick *)source;

  if(cargc<2) {
    controlreply(sender, "SETTEMPEMAIL FALSE args");
    return CMD_ERROR;
  }

  rup = findreguserbyID(atoi(cargv[0]));
  if(rup == NULL) {
    controlreply(sender, "SETTEMPEMAIL FALSE useridnotexist");
    return CMD_ERROR;
  }

  if(!UIsInactive(rup)) {
    controlreply(sender, "SETTEMPEMAIL FALSE accountactive");
    return CMD_ERROR;
  }

  email = cargv[1];
  error = email_to_error(email);
  if(error) {
    controlreply(sender, "SETTEMPEMAIL FALSE %s", error);
    return CMD_ERROR;
  }

  freesstring(rup->email);
  rup->email=getsstring(email,EMAILLEN);
  cs_log(sender,"SETTEMPEMAIL OK username %s email %s",rup->username, rup->email->content);

  csdb_updateuser(rup);
  sendemail(rup);

  controlreply(sender, "SETTEMPEMAIL TRUE");

  return CMD_OK;
}
Exemple #5
0
static void ns_cmd_sendpass(sourceinfo_t *si, int parc, char *parv[])
{
	myuser_t *mu;
	char *name = parv[0];
	char *newpass = NULL;
	char *key;
	metadata_t *md;
	enum specialoperation op = op_none;
	bool ismarked = false;
	char cmdtext[NICKLEN + 20];
	hook_user_needforce_t needforce_hdata;

	if (!name)
	{
		command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SENDPASS");
		command_fail(si, fault_needmoreparams, _("Syntax: SENDPASS <account>"));
		return;
	}

	if (parc > 1)
	{
		if (!strcasecmp(parv[1], "FORCE"))
			op = op_force;
		else if (!strcasecmp(parv[1], "CLEAR"))
			op = op_clear;
		else
		{
			command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SENDPASS");
			command_fail(si, fault_badparams, _("Syntax: SENDPASS <account> [FORCE|CLEAR]"));
			return;
		}
	}

	if (!(mu = myuser_find_by_nick(name)))
	{
		command_fail(si, fault_nosuch_target, _("\2%s\2 is not registered."), name);
		return;
	}

	if (is_soper(mu) && !has_priv(si, PRIV_ADMIN))
	{
		logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (is SOPER)", name);
		command_fail(si, fault_badparams, _("\2%s\2 belongs to a services operator; you need %s privilege to send the password."), name, PRIV_ADMIN);
		return;
	}

	if (mu->flags & MU_WAITAUTH)
	{
		command_fail(si, fault_badparams, _("\2%s\2 is not verified."), entity(mu)->name);
		return;
	}

	if ((md = metadata_find(mu, "private:mark:setter")))
	{
		ismarked = true;
		if (op == op_none)
		{
			logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (marked by \2%s\2)", entity(mu)->name, md->value);
			command_fail(si, fault_badparams, _("This operation cannot be performed on %s, because the account has been marked by %s."), entity(mu)->name, md->value);
			if (has_priv(si, PRIV_MARK))
			{
				snprintf(cmdtext, sizeof cmdtext, "SENDPASS %s FORCE", entity(mu)->name);
				command_fail(si, fault_badparams, _("Use %s to override this restriction."), cmdtext);
			}
			return;
		}
		else if (!has_priv(si, PRIV_MARK))
		{
			logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (marked by \2%s\2)", entity(mu)->name, md->value);
			command_fail(si, fault_noprivs, STR_NO_PRIVILEGE, PRIV_MARK);
			return;
		}
	}

	needforce_hdata.si = si;
	needforce_hdata.mu = mu;
	needforce_hdata.allowed = 1;

	hook_call_user_needforce(&needforce_hdata);

	if (!needforce_hdata.allowed)
	{
		ismarked = true;
		if (op == op_none)
		{
			logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (marked)", entity(mu)->name);
			command_fail(si, fault_badparams, _("This operation cannot be performed on %s, because the account has been marked."), entity(mu)->name);
			if (has_priv(si, PRIV_MARK))
			{
				snprintf(cmdtext, sizeof cmdtext, "SENDPASS %s FORCE", entity(mu)->name);
				command_fail(si, fault_badparams, _("Use %s to override this restriction."), cmdtext);
			}
			return;
		}
		else if (!has_priv(si, PRIV_MARK))
		{
			logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (marked)", entity(mu)->name);
			command_fail(si, fault_noprivs, STR_NO_PRIVILEGE, PRIV_MARK);
			return;
		}
	}

	if (op == op_clear)
	{
		if (metadata_find(mu, "private:setpass:key"))
		{
			metadata_delete(mu, "private:setpass:key");
			metadata_delete(mu, "private:sendpass:sender");
			metadata_delete(mu, "private:sendpass:timestamp");
			logcommand(si, CMDLOG_ADMIN, "SENDPASS:CLEAR: \2%s\2", entity(mu)->name);
			command_success_nodata(si, _("The password change key for \2%s\2 has been cleared."), entity(mu)->name);
		}
		else
			command_fail(si, fault_nochange, _("\2%s\2 did not have a password change key outstanding."), entity(mu)->name);
		return;
	}

	if (MOWGLI_LIST_LENGTH(&mu->logins) > 0)
	{
		command_fail(si, fault_noprivs, _("This operation cannot be performed on %s, because someone is logged in to it."), entity(mu)->name);
		return;
	}

	if (metadata_find(mu, "private:freeze:freezer"))
	{
		command_fail(si, fault_noprivs, _("%s has been frozen by the %s administration."), entity(mu)->name, me.netname);
		return;
	}

	if (command_find(si->service->commands, "SETPASS"))
	{
		if (metadata_find(mu, "private:setpass:key"))
		{
			command_fail(si, fault_alreadyexists, _("\2%s\2 already has a password change key outstanding."), entity(mu)->name);
			command_fail(si, fault_alreadyexists, _("Use SENDPASS %s CLEAR to clear it so that a new one can be sent."), entity(mu)->name);
			return;
		}

		if (ismarked)
		{
			wallops("%s sent the password for the \2MARKED\2 account %s.", get_oper_name(si), entity(mu)->name);
			if (md)
				command_success_nodata(si, _("Overriding MARK placed by %s on the account %s."), md->value, entity(mu)->name);
			else
				command_success_nodata(si, _("Overriding MARK on the account %s."), entity(mu)->name);
		}
		logcommand(si, CMDLOG_ADMIN, "SENDPASS: \2%s\2 (change key)", name);

		key = random_string(12);
		metadata_add(mu, "private:sendpass:sender", get_oper_name(si));
		metadata_add(mu, "private:sendpass:timestamp", number_to_string(time(NULL)));

		if (!sendemail(si->su != NULL ? si->su : si->service->me, mu, EMAIL_SETPASS, mu->email, key))
		{
			command_fail(si, fault_emailfail, _("Email send failed."));
			free(key);
			return;
		}

		metadata_add(mu, "private:setpass:key", crypt_string(key, gen_salt()));
		free(key);

		command_success_nodata(si, _("The password change key for \2%s\2 has been sent to \2%s\2."), entity(mu)->name, mu->email);
	}
	else {
		if (ismarked)
		{
			wallops("%s sent the password for the \2MARKED\2 account %s.", get_oper_name(si), entity(mu)->name);
			if (md)
				command_success_nodata(si, _("Overriding MARK placed by %s on the account %s."), md->value, entity(mu)->name);
			else
				command_success_nodata(si, _("Overriding MARK on the account %s."), entity(mu)->name);
		}
		logcommand(si, CMDLOG_ADMIN, "SENDPASS: \2%s\2", name);

		newpass = random_string(12);
		metadata_add(mu, "private:sendpass:sender", get_oper_name(si));
		metadata_add(mu, "private:sendpass:timestamp", number_to_string(time(NULL)));

		if (!sendemail(si->su != NULL ? si->su : si->service->me, mu, EMAIL_SENDPASS, mu->email, newpass))
		{
			command_fail(si, fault_emailfail, _("Email send failed."));
			free(newpass);
			return;
		}

		set_password(mu, newpass);
		free(newpass);

		command_success_nodata(si, _("The password for \2%s\2 has been sent to \2%s\2."), entity(mu)->name, mu->email);

		if (mu->flags & MU_NOPASSWORD)
		{
			mu->flags &= ~MU_NOPASSWORD;
			command_success_nodata(si, _("The \2%s\2 flag has been removed for account \2%s\2."), "NOPASSWORD", entity(mu)->name);
		}
	}
}
Exemple #6
0
static void
ns_cmd_sendpass(struct sourceinfo *si, int parc, char *parv[])
{
	struct myuser *mu;
	char *name = parv[0];
	char *key;
	enum specialoperation op = op_none;
	bool ismarked = false;

	if (!name)
	{
		command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SENDPASS");
		command_fail(si, fault_needmoreparams, _("Syntax: SENDPASS <account>"));
		return;
	}

	if (parc > 1)
	{
		if (!has_priv(si, PRIV_USER_SENDPASS))
		{
			command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED);
			return;
		}
		else if (!strcasecmp(parv[1], "FORCE"))
			op = op_force;
		else if (!strcasecmp(parv[1], "CLEAR"))
			op = op_clear;
		else
		{
			command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SENDPASS");
			command_fail(si, fault_badparams, _("Syntax: SENDPASS <account> [FORCE|CLEAR]"));
			return;
		}
	}

	if (!(mu = myuser_find_by_nick(name)))
	{
		command_fail(si, fault_nosuch_target, STR_IS_NOT_REGISTERED, name);
		return;
	}

	if (mu->flags & MU_WAITAUTH)
	{
		command_fail(si, fault_badparams, _("\2%s\2 is not verified."), entity(mu)->name);
		return;
	}

	if (metadata_find(mu, "private:mark:setter"))
	{
		ismarked = true;
		// don't want to disclose this, so just go ahead...
	}

	if (op == op_clear)
	{
		if (metadata_find(mu, "private:setpass:key"))
		{
			logcommand(si, CMDLOG_ADMIN, "SENDPASS:CLEAR: \2%s\2", entity(mu)->name);
			metadata_delete(mu, "private:setpass:key");
			metadata_delete(mu, "private:sendpass:sender");
			metadata_delete(mu, "private:sendpass:timestamp");
			command_success_nodata(si, _("The password change key for \2%s\2 has been cleared."), entity(mu)->name);
		}
		else
			command_fail(si, fault_nochange, _("\2%s\2 did not have a password change key outstanding."), entity(mu)->name);
		return;
	}

	if (MOWGLI_LIST_LENGTH(&mu->logins) > 0)
	{
		if (si->smu == mu)
			command_fail(si, fault_already_authed, _("You are logged in and can change your password using the SET PASSWORD command."));
		else
			command_fail(si, fault_noprivs, _("This operation cannot be performed on %s, because someone is logged in to it."), entity(mu)->name);
		return;
	}

	if (metadata_find(mu, "private:freeze:freezer"))
	{
		command_fail(si, fault_noprivs, _("%s has been frozen by the %s administration."), entity(mu)->name, me.netname);
		return;
	}

	if (metadata_find(mu, "private:setpass:key"))
	{
		command_fail(si, fault_alreadyexists, _("\2%s\2 already has a password change key outstanding."), entity(mu)->name);
		if (has_priv(si, PRIV_USER_SENDPASS))
			command_fail(si, fault_alreadyexists, _("Use SENDPASS %s CLEAR to clear it so that a new one can be sent."), entity(mu)->name);
		return;
	}

	key = random_string(12);

	const char *const hash = crypt_password(key);

	if (!hash)
	{
		command_fail(si, fault_internalerror, _("Hash generation for password change key failed."));
		sfree(key);
		return;
	}
	if (sendemail(si->su != NULL ? si->su : si->service->me, mu, EMAIL_SETPASS, mu->email, key))
	{
		if (ismarked)
			wallops("%s sent the password for the \2MARKED\2 account %s.", get_oper_name(si), entity(mu)->name);
		logcommand(si, CMDLOG_ADMIN, "SENDPASS: \2%s\2 (change key)", name);
		metadata_add(mu, "private:sendpass:sender", get_oper_name(si));
		metadata_add(mu, "private:sendpass:timestamp", number_to_string(time(NULL)));
		metadata_add(mu, "private:setpass:key", hash);
		command_success_nodata(si, _("The password change key for \2%s\2 has been sent to the corresponding email address."), entity(mu)->name);
	}
	else
		command_fail(si, fault_emailfail, _("Email send failed."));
	sfree(key);
}
Exemple #7
0
/* SET EMAIL <new address> */
static void ns_cmd_set_email(sourceinfo_t *si, int parc, char *parv[])
{
	char *email = parv[0];
	metadata_t *md;

	if (!email)
	{
		command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "EMAIL");
		command_fail(si, fault_needmoreparams, _("Syntax: SET EMAIL <new e-mail>"));
		return;
	}

	if (si->smu->flags & MU_WAITAUTH)
	{
		command_fail(si, fault_noprivs, _("Please verify your original registration before changing your e-mail address."));
		return;
	}

	if (!strcasecmp(si->smu->email, email))
	{
		md = metadata_find(si->smu, "private:verify:emailchg:newemail");
		if (md != NULL)
		{
			command_success_nodata(si, _("The email address change to \2%s\2 has been cancelled."), md->value);
			metadata_delete(si->smu, "private:verify:emailchg:key");
			metadata_delete(si->smu, "private:verify:emailchg:newemail");
			metadata_delete(si->smu, "private:verify:emailchg:timestamp");
		}
		else
			command_fail(si, fault_nochange, _("The email address for account \2%s\2 is already set to \2%s\2."), entity(si->smu)->name, si->smu->email);
		return;
	}

	if (!validemail(email))
	{
		command_fail(si, fault_badparams, _("\2%s\2 is not a valid email address."), email);
		return;
	}

	if (me.auth == AUTH_EMAIL)
	{
		unsigned long key = makekey();

		metadata_add(si->smu, "private:verify:emailchg:key", number_to_string(key));
		metadata_add(si->smu, "private:verify:emailchg:newemail", email);
		metadata_add(si->smu, "private:verify:emailchg:timestamp", number_to_string(CURRTIME));

		if (!sendemail(si->su != NULL ? si->su : si->service->me, EMAIL_SETEMAIL, si->smu, number_to_string(key)))
		{
			command_fail(si, fault_emailfail, _("Sending email failed, sorry! Your email address is unchanged."));
			metadata_delete(si->smu, "private:verify:emailchg:key");
			metadata_delete(si->smu, "private:verify:emailchg:newemail");
			metadata_delete(si->smu, "private:verify:emailchg:timestamp");
			return;
		}

		logcommand(si, CMDLOG_SET, "SET:EMAIL: \2%s\2 (\2%s\2 -> \2%s\2) (awaiting verification)", entity(si->smu)->name, si->smu->email, email);
		command_success_nodata(si, _("An email containing email changing instructions has been sent to \2%s\2."), email);
		command_success_nodata(si, _("Your email address will not be changed until you follow these instructions."));

		return;
	}

	myuser_set_email(si->smu, email);

	logcommand(si, CMDLOG_SET, "SET:EMAIL: \2%s\2 (\2%s\2 -> \2%s\2)", entity(si->smu)->name, si->smu->email, email);
	command_success_nodata(si, _("The email address for account \2%s\2 has been changed to \2%s\2."), entity(si->smu)->name, si->smu->email);
}
Exemple #8
0
static void ns_cmd_register(sourceinfo_t *si, int parc, char *parv[])
{
	myuser_t *mu;
	mynick_t *mn = NULL;
	mowgli_node_t *n;
	const char *account;
	const char *pass;
	const char *email;
	char lau[BUFSIZE], lao[BUFSIZE];
	hook_user_register_check_t hdata;
	hook_user_req_t req;

	if (si->smu)
	{
		command_fail(si, fault_already_authed, _("You are already logged in as \2%s\2."), entity(si->smu)->name);
		if (si->su != NULL && !mynick_find(si->su->nick) &&
				command_find(si->service->commands, "GROUP"))
			command_fail(si, fault_already_authed, _("Use %s to register %s to your account."), "GROUP", si->su->nick);
		return;
	}

	if (nicksvs.no_nick_ownership || si->su == NULL)
		account = parv[0], pass = parv[1], email = parv[2];
	else
		account = si->su->nick, pass = parv[0], email = parv[1];

	if (!account || !pass || !email)
	{
		command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "REGISTER");
		if (nicksvs.no_nick_ownership || si->su == NULL)
			command_fail(si, fault_needmoreparams, _("Syntax: REGISTER <account> <password> <email>"));
		else
			command_fail(si, fault_needmoreparams, _("Syntax: REGISTER <password> <email>"));
		return;
	}

	if (strlen(pass) >= PASSLEN)
	{
		command_fail(si, fault_badparams, STR_INVALID_PARAMS, "REGISTER");
		command_fail(si, fault_badparams, _("Registration passwords may not be longer than \2%d\2 characters."), PASSLEN - 1);
		return;
	}

	if (!nicksvs.no_nick_ownership && si->su == NULL && user_find_named(account))
	{
		command_fail(si, fault_noprivs, _("A user matching this account is already on IRC."));
		return;
	}

	if (!nicksvs.no_nick_ownership && IsDigit(*account))
	{
		command_fail(si, fault_badparams, _("For security reasons, you can't register your UID."));
		command_fail(si, fault_badparams, _("Please change to a real nickname, and try again."));
		return;
	}

	if (nicksvs.no_nick_ownership || si->su == NULL)
	{
		if (strchr(account, ' ') || strchr(account, '\n') || strchr(account, '\r') || account[0] == '=' || account[0] == '#' || account[0] == '@' || account[0] == '+' || account[0] == '%' || account[0] == '!' || strchr(account, ','))
		{
			command_fail(si, fault_badparams, _("The account name \2%s\2 is invalid."), account);
			return;
		}
	}

	if (strlen(account) >= NICKLEN)
	{
		command_fail(si, fault_badparams, _("The account name \2%s\2 is invalid."), account);
		return;
	}

	if ((si->su != NULL && !strcasecmp(pass, si->su->nick)) || !strcasecmp(pass, account))
	{
		command_fail(si, fault_badparams, _("You cannot use your nickname as a password."));
		if (nicksvs.no_nick_ownership || si->su == NULL)
			command_fail(si, fault_needmoreparams, _("Syntax: REGISTER <account> <password> <email>"));
		else
			command_fail(si, fault_needmoreparams, _("Syntax: REGISTER <password> <email>"));
		return;
	}

	/* make sure it isn't registered already */
	if (nicksvs.no_nick_ownership ? myuser_find(account) != NULL : mynick_find(account) != NULL)
	{
		command_fail(si, fault_alreadyexists, _("\2%s\2 is already registered."), account);
		return;
	}

	if ((unsigned int)(CURRTIME - ratelimit_firsttime) > config_options.ratelimit_period)
		ratelimit_count = 0, ratelimit_firsttime = CURRTIME;

	/* Still do flood priv checking because the user may be in the ircop operclass */
	if (ratelimit_count > config_options.ratelimit_uses && !has_priv(si, PRIV_FLOOD))
	{
		command_fail(si, fault_toomany, _("The system is currently too busy to process your registration, please try again later."));
		slog(LG_INFO, "NICKSERV:REGISTER:THROTTLED: \2%s\2 by \2%s\2", account, si->su != NULL ? si->su->nick : get_source_name(si));
		return;
	}

	hdata.si = si;
	hdata.account = account;
	hdata.email = email;
	hdata.password = pass;
	hdata.approved = 0;
	hook_call_user_can_register(&hdata);
	if (hdata.approved != 0)
		return;
	if (!nicksvs.no_nick_ownership)
	{
		hook_call_nick_can_register(&hdata);
		if (hdata.approved != 0)
			return;
	}

	if (!validemail(email))
	{
		command_fail(si, fault_badparams, _("\2%s\2 is not a valid email address."), email);
		return;
	}

	if (!email_within_limits(email))
	{
		command_fail(si, fault_toomany, _("\2%s\2 has too many accounts registered."), email);
		return;
	}

	mu = myuser_add(account, auth_module_loaded ? "*" : pass, email, config_options.defuflags | MU_NOBURSTLOGIN | (auth_module_loaded ? MU_CRYPTPASS : 0));
	mu->registered = CURRTIME;
	mu->lastlogin = CURRTIME;
	if (!nicksvs.no_nick_ownership)
	{
		mn = mynick_add(mu, entity(mu)->name);
		mn->registered = CURRTIME;
		mn->lastseen = CURRTIME;
	}
	if (config_options.ratelimit_uses && config_options.ratelimit_period)
		ratelimit_count++;

	if (auth_module_loaded)
	{
		if (!verify_password(mu, pass))
		{
			command_fail(si, fault_authfail, _("Invalid password for \2%s\2."), entity(mu)->name);
			bad_password(si, mu);
			object_unref(mu);
			return;
		}
	}

	if (me.auth == AUTH_EMAIL)
	{
		char *key = random_string(12);
		mu->flags |= MU_WAITAUTH;

		metadata_add(mu, "private:verify:register:key", key);
		metadata_add(mu, "private:verify:register:timestamp", number_to_string(time(NULL)));

		if (!sendemail(si->su != NULL ? si->su : si->service->me, mu, EMAIL_REGISTER, mu->email, key))
		{
			command_fail(si, fault_emailfail, _("Sending email failed, sorry! Registration aborted."));
			object_unref(mu);
			free(key);
			return;
		}

		command_success_nodata(si, _("An email containing nickname activation instructions has been sent to \2%s\2."), mu->email);
		command_success_nodata(si, _("If you do not complete registration within one day, your nickname will expire."));

		free(key);
	}

	if (si->su != NULL)
	{
		si->su->myuser = mu;
		n = mowgli_node_create();
		mowgli_node_add(si->su, n, &mu->logins);

		if (!(mu->flags & MU_WAITAUTH))
			/* only grant ircd registered status if it's verified */
			ircd_on_login(si->su, mu, NULL);
	}

	command_add_flood(si, FLOOD_MODERATE);

	if (!nicksvs.no_nick_ownership && si->su != NULL)
		logcommand(si, CMDLOG_REGISTER, "REGISTER: \2%s\2 to \2%s\2", account, email);
	else
		logcommand(si, CMDLOG_REGISTER, "REGISTER: \2%s\2 to \2%s\2 by \2%s\2", account, email, si->su != NULL ? si->su->nick : get_source_name(si));

	if (is_soper(mu))
	{
		wallops("%s registered the nick \2%s\2 and gained services operator privileges.", get_oper_name(si), entity(mu)->name);
		logcommand(si, CMDLOG_ADMIN, "SOPER: \2%s\2 as \2%s\2", get_oper_name(si), entity(mu)->name);
	}

	command_success_nodata(si, _("\2%s\2 is now registered to \2%s\2, with the password \2%s\2."), entity(mu)->name, mu->email, pass);
	hook_call_user_register(mu);

	if (si->su != NULL)
	{
		snprintf(lau, BUFSIZE, "%s@%s", si->su->user, si->su->vhost);
		metadata_add(mu, "private:host:vhost", lau);

		snprintf(lao, BUFSIZE, "%s@%s", si->su->user, si->su->host);
		metadata_add(mu, "private:host:actual", lao);
	}

	if (!(mu->flags & MU_WAITAUTH))
	{
		req.si = si;
		req.mu = mu;
		req.mn = mn;
		hook_call_user_verify_register(&req);
	}
}
int csa_docreateaccount(void *source, int cargc, char **cargv) {
  nick *sender=(nick *)source;
  int execute;
  char *error_username = NULL, *error_password = NULL, *error_email = NULL;
  char *username = NULL, *password = NULL, *email = NULL;
  char account_info[512];
  char passbuf[512];
  int do_create;
  int activate;

  if(cargc<5) {
    controlreply(sender, "CREATEACCOUNT FALSE args");
    return CMD_ERROR;
  }

  execute = cargv[0][0] == '1';
  if(strcmp(cargv[1], "0"))
    username = cargv[1];
  if(strcmp(cargv[2], "0"))
    email = cargv[2];
  if(strcmp(cargv[3], "0")) {
    int errorcode = decrypt_password(createaccountsecret, KEY_BITS, passbuf, sizeof(passbuf), cargv[3]);
    if(errorcode) {
      Error("chanserv_relay",ERR_WARNING,"createaccount unable to decrypt password, error code: %d", errorcode);
      controlreply(sender, "CREATEACCOUNT FALSE args");
      return CMD_ERROR;
    }
    password = passbuf;
  }
  activate = cargv[4][0] == '1';

  if(username) {
    if (findreguserbynick(username)) {
      error_username = "******";
    } else if(csa_checkaccountname_r(username)) {
      error_username = "******";
    }
  }

  if(email)
    error_email = email_to_error(email);

  if(password) {
    int r = csa_checkpasswordquality(password);
    if(r == QM_PWTOSHORT) {
      error_password = "******";
    } else if(r == QM_PWTOLONG) {
      error_password = "******";
    } else if(r == QM_PWTOWEAK) {
      error_password = "******";
    } else if(r == QM_PWINVALID) {
      error_password = "******";
    } else if(r != -1) {
      error_password = "******";
    }
  }

  if(execute && email && password && username && !error_email && !error_password && !error_username) {
    reguser *rup;
    do_create = 1;

    rup = csa_createaccount(username, password, email);

    if(!activate)
      USetInactive(rup);

    cs_log(sender,"CREATEACCOUNT created auth %s (%s) %s",rup->username,rup->email->content,activate?"(active)": "(inactive)");
    csdb_createuser(rup);
    snprintf(account_info, sizeof(account_info), " %u %lu", rup->ID, (unsigned long)rup->lastpasschange);

    if(!activate)
      sendemail(rup);
  } else {
    account_info[0] = '\0';
    do_create = 0;
  }

  controlreply(sender, "CREATEACCOUNT %s%s%s%s%s%s%s%s",
    do_create ? "TRUE" : "FALSE",
    account_info,
    email && error_email ? " " : "", email && error_email ? error_email : "",
    password && error_password ? " " : "", password && error_password ? error_password : "",
    username && error_username ? " " : "", username && error_username ? error_username : ""
  );

  return CMD_OK;
}