/* nickserv.c - Nick/authentication service
* Copyright 2000-2004 srvx Development Team
*
- * This file is part of srvx.
+ * This file is part of x3.
*
- * srvx is free software; you can redistribute it and/or modify
+ * x3 is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
#include "chanserv.h"
#include "conf.h"
+#include "config.h"
#include "global.h"
#include "modcmd.h"
#include "opserv.h" /* for gag_create(), opserv_bad_channel() */
#include "saxdb.h"
#include "sendmail.h"
#include "timeq.h"
+#include "x3ldap.h"
-#ifdef HAVE_REGEX_H
-#include <regex.h>
+#include <tre/regex.h>
+
+#ifdef WITH_LDAP
+#include <ldap.h>
#endif
#define NICKSERV_CONF_NAME "services/nickserv"
#define KEY_VALID_HANDLE_REGEX "valid_handle_regex"
#define KEY_VALID_ACCOUNT_REGEX "valid_account_regex"
#define KEY_VALID_NICK_REGEX "valid_nick_regex"
+#define KEY_VALID_FAKEHOST_REGEX "valid_fakehost_regex"
#define KEY_DB_BACKUP_FREQ "db_backup_freq"
#define KEY_MODOPER_LEVEL "modoper_level"
#define KEY_SET_EPITHET_LEVEL "set_epithet_level"
#define KEY_SET_TITLE_LEVEL "set_title_level"
#define KEY_SET_FAKEHOST_LEVEL "set_fakehost_level"
+#define KEY_DENIED_FAKEHOST_WORDS "denied_fakehost_words"
#define KEY_TITLEHOST_SUFFIX "titlehost_suffix"
+#define KEY_AUTO_OPER "auto_oper"
+#define KEY_AUTO_ADMIN "auto_admin"
#define KEY_FLAG_LEVELS "flag_levels"
#define KEY_HANDLE_EXPIRE_FREQ "handle_expire_freq"
#define KEY_ACCOUNT_EXPIRE_FREQ "account_expire_freq"
#define KEY_EMAIL_VISIBLE_LEVEL "email_visible_level"
#define KEY_EMAIL_ENABLED "email_enabled"
#define KEY_EMAIL_REQUIRED "email_required"
+#define KEY_SYNC_LOG "sync_log"
#define KEY_COOKIE_TIMEOUT "cookie_timeout"
#define KEY_ACCOUNTS_PER_EMAIL "accounts_per_email"
#define KEY_EMAIL_SEARCH_LEVEL "email_search_level"
+#define KEY_DEFAULT_STYLE "default_style"
#define KEY_ID "id"
#define KEY_PASSWD "passwd"
#define KEY_NICKS "nicks"
#define KEY_MASKS "masks"
+#define KEY_IGNORES "ignores"
#define KEY_OPSERV_LEVEL "opserv_level"
#define KEY_FLAGS "flags"
#define KEY_REGISTER_ON "register"
#define KEY_ANNOUNCEMENTS "announcements"
#define KEY_MAXLOGINS "maxlogins"
#define KEY_FAKEHOST "fakehost"
+#define KEY_NOTE_NOTE "note"
+#define KEY_NOTE_SETTER "setter"
+#define KEY_NOTE_DATE "date"
+#define KEY_FORCE_HANDLES_LOWERCASE "force_handles_lowercase"
+
+#define KEY_LDAP_ENABLE "ldap_enable"
+
+#ifdef WITH_LDAP
+#define KEY_LDAP_URI "ldap_uri"
+#define KEY_LDAP_BASE "ldap_base"
+#define KEY_LDAP_DN_FMT "ldap_dn_fmt"
+#define KEY_LDAP_VERSION "ldap_version"
+#define KEY_LDAP_AUTOCREATE "ldap_autocreate"
+#define KEY_LDAP_ADMIN_DN "ldap_admin_dn"
+#define KEY_LDAP_ADMIN_PASS "ldap_admin_pass"
+#define KEY_LDAP_FIELD_ACCOUNT "ldap_field_account"
+#define KEY_LDAP_FIELD_PASSWORD "ldap_field_password"
+#define KEY_LDAP_FIELD_EMAIL "ldap_field_email"
+#define KEY_LDAP_OBJECT_CLASSES "ldap_object_classes"
+#define KEY_LDAP_OPER_GROUP_DN "ldap_oper_group_dn"
+#define KEY_LDAP_FIELD_GROUP_MEMBER "ldap_field_group_member"
+#define KEY_LDAP_TIMEOUT "ldap_timeout"
+#endif
#define NICKSERV_VALID_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
#define NICKSERV_FUNC(NAME) MODCMD_FUNC(NAME)
-#define OPTION_FUNC(NAME) int NAME(struct userNode *user, struct handle_info *hi, UNUSED_ARG(unsigned int override), unsigned int argc, char *argv[])
+#define OPTION_FUNC(NAME) int NAME(struct svccmd *cmd, struct userNode *user, struct handle_info *hi, UNUSED_ARG(unsigned int override), unsigned int argc, char *argv[])
typedef OPTION_FUNC(option_func_t);
DEFINE_LIST(handle_info_list, struct handle_info*);
#define NICKSERV_MIN_PARMS(N) do { \
if (argc < N) { \
reply("MSG_MISSING_PARAMS", argv[0]); \
- svccmd_send_help(user, nickserv, cmd); \
+ svccmd_send_help_brief(user, nickserv, cmd); \
return 0; \
} } while (0)
struct userList curr_helpers;
const char *handle_flags = HANDLE_FLAGS;
+extern struct string_list *autojoin_channels;
static struct module *nickserv_module;
static struct service *nickserv_service;
static struct log_type *NS_LOG;
static char handle_inverse_flags[256];
static unsigned int flag_access_levels[32];
static const struct message_entry msgtab[] = {
+ { "NSMSG_NO_ANGLEBRACKETS", "The < and > in help indicate that that word is a required parameter, but DO NOT actually type them in messages to me." },
{ "NSMSG_HANDLE_EXISTS", "Account $b%s$b is already registered." },
+ { "NSMSG_HANDLE_TOLONG", "The account name %s is too long. Account names must be %lu characters or less."},
{ "NSMSG_PASSWORD_SHORT", "Your password must be at least %lu characters long." },
{ "NSMSG_PASSWORD_ACCOUNT", "Your password may not be the same as your account name." },
- { "NSMSG_PASSWORD_DICTIONARY", "Your password should not be the word \"password\", or any other dictionary word." },
+ { "NSMSG_PASSWORD_DICTIONARY", "Your password is too simple. You must choose a password that is not just a word or name." },
{ "NSMSG_PASSWORD_READABLE", "Your password must have at least %lu digit(s), %lu capital letter(s), and %lu lower-case letter(s)." },
+ { "NSMSG_LDAP_FAIL", "There was a problem in contacting the account server (ldap): %s. Please try again later." },
+ { "NSMSG_LDAP_FAIL_ADD", "There was a problem in adding account %s to ldap: %s." },
+ { "NSMSG_LDAP_FAIL_SEND_EMAIL", "There was a problem in storing your email address in the account server (ldap): %s. Please try again later." },
+ { "NSMSG_LDAP_FAIL_GET_EMAIL", "There was a problem in retrieving your email address from the account server (ldap): %s. Please try again later." },
{ "NSMSG_PARTIAL_REGISTER", "Account has been registered to you; nick was already registered to someone else." },
{ "NSMSG_OREGISTER_VICTIM", "%s has registered a new account for you (named %s)." },
{ "NSMSG_OREGISTER_H_SUCCESS", "Account has been registered." },
{ "NSMSG_COOKIE_LIVE", "Account $b%s$b already has a cookie active. Please either finish using that cookie, wait for it to expire, or auth to the account and use the $bdelcookie$b command." },
{ "NSMSG_EMAIL_UNACTIVATED", "That email address already has an unused cookie outstanding. Please use the cookie or wait for it to expire." },
{ "NSMSG_NO_COOKIE", "Your account does not have any cookie issued right now." },
+ { "NSMSG_NO_COOKIE_FOREIGN", "The account $b%s$b does not have any cookie issued right now." },
{ "NSMSG_CANNOT_COOKIE", "You cannot use that kind of cookie when you are logged in." },
{ "NSMSG_BAD_COOKIE", "That cookie is not the right one. Please make sure you are copying it EXACTLY from the email; it is case-sensitive, so $bABC$b is different from $babc$b." },
{ "NSMSG_HANDLE_ACTIVATED", "Your account is now activated (with the password you entered when you registered). You are now authenticated to your account." },
{ "NSMSG_PASSWORD_CHANGED", "You have successfully changed your password to what you requested with the $bresetpass$b command." },
{ "NSMSG_EMAIL_PROHIBITED", "%s may not be used as an email address: %s" },
- { "NSMSG_EMAIL_OVERUSED", "There are already the maximum number of accounts associated with that email address." },
+ { "NSMSG_EMAIL_OVERUSED", "That email address already has an account. Use RESETPASS if you forgot your password." },
{ "NSMSG_EMAIL_SAME", "That is the email address already there; no need to change it." },
{ "NSMSG_EMAIL_CHANGED", "You have successfully changed your email address." },
{ "NSMSG_BAD_COOKIE_TYPE", "Your account had bad cookie type %d; sorry. I am confused. Please report this bug." },
{ "NSMSG_MUST_TIME_OUT", "You must wait for cookies of that type to time out." },
{ "NSMSG_ATE_COOKIE", "I ate the cookie for your account. You may now have another." },
+ { "NSMSG_ATE_FOREIGN_COOKIE", "I ate the cookie for account $b%s$b. It may now have another." },
{ "NSMSG_USE_RENAME", "You are already authenticated to account $b%s$b -- contact the support staff to rename your account." },
{ "NSMSG_ALREADY_REGISTERING", "You have already used $bREGISTER$b once this session; you may not use it again." },
- { "NSMSG_REGISTER_BAD_NICKMASK", "Could not recognize $b%s$b as either a current nick or a hostmask." },
+ { "NSMSG_REGISTER_BAD_NICKMASK", "You must provide a hostmask, or online nick to generate one automatically. (or set a default hostmask in the config such as *@*)." },
{ "NSMSG_NICK_NOT_REGISTERED", "Nick $b%s$b has not been registered to any account." },
{ "NSMSG_HANDLE_NOT_FOUND", "Could not find your account -- did you register yet?" },
{ "NSMSG_ALREADY_AUTHED", "You are already authed to account $b%s$b; you must reconnect to auth to a different account." },
{ "NSMSG_USER_PREV_AUTH", "$b%s$b is already authenticated." },
{ "NSMSG_USER_PREV_STAMP", "$b%s$b has authenticated to an account once and cannot authenticate again." },
{ "NSMSG_BAD_MAX_LOGINS", "MaxLogins must be at most %d." },
+ { "NSMSG_BAD_ADVANCED", "Advanced must be either 1 to enable it or 0 to disable it." },
{ "NSMSG_LANGUAGE_NOT_FOUND", "Language $b%s$b is not supported; $b%s$b was the closest available match." },
{ "NSMSG_MAX_LOGINS", "Your account already has its limit of %d user(s) logged in." },
{ "NSMSG_STAMPED_REGISTER", "You have already authenticated to an account once this session; you may not register a new account." },
{ "NSMSG_STAMPED_AUTH", "You have already authenticated to an account once this session; you may not authenticate to another." },
{ "NSMSG_STAMPED_RESETPASS", "You have already authenticated to an account once this session; you may not reset your password to authenticate again." },
{ "NSMSG_STAMPED_AUTHCOOKIE", "You have already authenticated to an account once this session; you may not use a cookie to authenticate to another account." },
- { "NSMSG_TITLE_INVALID", "Titles cannot contain any dots; please choose another." },
+ { "NSMSG_TITLE_INVALID", "Titles may contain only a-z, A-Z, 0-9, and '-'. Please choose another." },
+ { "NSMSG_TITLE_TRUNCATED", "That title combined with the user's account name would result in a truncated host; please choose a shorter title." },
{ "NSMSG_FAKEHOST_INVALID", "Fake hosts must be shorter than %d characters and cannot start with a dot." },
- { "NSMSG_HANDLEINFO_ON", "Account information for $b%s$b:" },
- { "NSMSG_HANDLEINFO_ID", " Account ID: %lu" },
- { "NSMSG_HANDLEINFO_REGGED", " Registered on: %s" },
- { "NSMSG_HANDLEINFO_LASTSEEN", " Last seen: %s" },
- { "NSMSG_HANDLEINFO_LASTSEEN_NOW", " Last seen: Right now!" },
- { "NSMSG_HANDLEINFO_VACATION", " On vacation." },
- { "NSMSG_HANDLEINFO_EMAIL_ADDR", " Email address: %s" },
- { "NSMSG_HANDLEINFO_COOKIE_ACTIVATION", " Cookie: There is currently an activation cookie issued for this account" },
- { "NSMSG_HANDLEINFO_COOKIE_PASSWORD", " Cookie: There is currently a password change cookie issued for this account" },
- { "NSMSG_HANDLEINFO_COOKIE_EMAIL", " Cookie: There is currently an email change cookie issued for this account" },
- { "NSMSG_HANDLEINFO_COOKIE_ALLOWAUTH", " Cookie: There is currently an allowauth cookie issued for this account" },
- { "NSMSG_HANDLEINFO_COOKIE_UNKNOWN", " Cookie: There is currently an unknown cookie issued for this account" },
- { "NSMSG_HANDLEINFO_INFOLINE", " Infoline: %s" },
- { "NSMSG_HANDLEINFO_FLAGS", " Flags: %s" },
- { "NSMSG_HANDLEINFO_EPITHET", " Epithet: %s" },
- { "NSMSG_HANDLEINFO_FAKEHOST", " Fake host: %s" },
- { "NSMSG_HANDLEINFO_LAST_HOST", " Last quit hostmask: %s" },
- { "NSMSG_HANDLEINFO_LAST_HOST_UNKNOWN", " Last quit hostmask: Unknown" },
- { "NSMSG_HANDLEINFO_NICKS", " Nickname(s): %s" },
- { "NSMSG_HANDLEINFO_MASKS", " Hostmask(s): %s" },
- { "NSMSG_HANDLEINFO_CHANNELS", " Channel(s): %s" },
- { "NSMSG_HANDLEINFO_CURRENT", " Current nickname(s): %s" },
- { "NSMSG_HANDLEINFO_DNR", " Do-not-register (by %s): %s" },
+ { "NSMSG_HANDLEINFO_ON", "$bAccount Information for %s$b" },
+ { "NSMSG_HANDLEINFO_END", "----------End of Account Info-----------" },
+ { "NSMSG_HANDLEINFO_ID", "Account ID: %lu" },
+ { "NSMSG_HANDLEINFO_REGGED", "Registered on: %s" },
+ { "NSMSG_HANDLEINFO_LASTSEEN", "Last seen: %s" },
+ { "NSMSG_HANDLEINFO_LASTSEEN_NOW", "Last seen: Right now!" },
+ { "NSMSG_HANDLEINFO_VACATION", "On vacation." },
+ { "NSMSG_HANDLEINFO_EMAIL_ADDR", "Email address: %s" },
+ { "NSMSG_HANDLEINFO_COOKIE_ACTIVATION", "Cookie: There is currently an activation cookie issued for this account" },
+ { "NSMSG_HANDLEINFO_COOKIE_PASSWORD", "Cookie: There is currently a password change cookie issued for this account" },
+ { "NSMSG_HANDLEINFO_COOKIE_EMAIL", "Cookie: There is currently an email change cookie issued for this account" },
+ { "NSMSG_HANDLEINFO_COOKIE_ALLOWAUTH", "Cookie: There is currently an allowauth cookie issued for this account" },
+ { "NSMSG_HANDLEINFO_COOKIE_UNKNOWN", "Cookie: There is currently an unknown cookie issued for this account" },
+ { "NSMSG_HANDLEINFO_INFOLINE", "Infoline: %s" },
+ { "NSMSG_HANDLEINFO_FLAGS", "Flags: %s" },
+ { "NSMSG_HANDLEINFO_EPITHET", "Epithet: %s" },
+ { "NSMSG_HANDLEINFO_NOTE", "Note (by %s on %s): %s " },
+ { "NSMSG_HANDLEINFO_FAKEHOST", "Fake host: %s" },
+ { "NSMSG_HANDLEINFO_LAST_HOST", "Last quit hostmask: %s" },
+ { "NSMSG_HANDLEINFO_LAST_HOST_UNKNOWN", "Last quit hostmask: Unknown" },
+ { "NSMSG_HANDLEINFO_NICKS", "Nickname(s): %s" },
+ { "NSMSG_HANDLEINFO_MASKS", "Hostmask(s): %s" },
+ { "NSMSG_HANDLEINFO_IGNORES", "Ignore(s): %s" },
+ { "NSMSG_HANDLEINFO_CHANNELS", "Channel(s): %s" },
+ { "NSMSG_HANDLEINFO_CURRENT", "Current nickname(s): %s" },
+ { "NSMSG_HANDLEINFO_DNR", "Do-not-register (by %s): %s" },
{ "NSMSG_USERINFO_AUTHED_AS", "$b%s$b is authenticated to account $b%s$b." },
{ "NSMSG_USERINFO_NOT_AUTHED", "$b%s$b is not authenticated to any account." },
{ "NSMSG_NICKINFO_OWNER", "Nick $b%s$b is owned by account $b%s$b." },
{ "NSMSG_MASK_INVALID", "$b%s$b is an invalid hostmask." },
{ "NSMSG_ADDMASK_ALREADY", "$b%s$b is already a hostmask in your account." },
{ "NSMSG_ADDMASK_SUCCESS", "Hostmask %s added." },
+ { "NSMSG_ADDIGNORE_ALREADY", "$b%s$b is already an ignored hostmask in your account." },
+ { "NSMSG_ADDIGNORE_SUCCESS", "Hostmask %s added." },
{ "NSMSG_DELMASK_NOTLAST", "You may not delete your last hostmask." },
{ "NSMSG_DELMASK_SUCCESS", "Hostmask %s deleted." },
{ "NSMSG_DELMASK_NOT_FOUND", "Unable to find mask to be deleted." },
{ "NSMSG_DB_UNREADABLE", "Unable to read database file %s; check the log for more information." },
{ "NSMSG_DB_MERGED", "$N merged DB from %s (in "FMT_TIME_T".%03lu seconds)." },
{ "NSMSG_HANDLE_CHANGED", "$b%s$b's account name has been changed to $b%s$b." },
- { "NSMSG_BAD_HANDLE", "Account $b%s$b not registered because it is in use by a network service, is too long, or contains invalid characters." },
+ { "NSMSG_BAD_HANDLE", "Account $b%s$b is not allowed because it is reserved, is too long, or contains invalid characters." },
{ "NSMSG_BAD_NICK", "Nickname $b%s$b not registered because it is in use by a network service, is too long, or contains invalid characters." },
{ "NSMSG_BAD_EMAIL_ADDR", "Please use a well-formed email address." },
{ "NSMSG_FAIL_RENAME", "Account $b%s$b not renamed to $b%s$b because it is in use by a network services, or contains invalid characters." },
{ "NSMSG_RECLAIMED_SVSNICK", "Forcibly changed %s's nick." },
{ "NSMSG_RECLAIMED_KILL", "Disconnected %s from the network." },
{ "NSMSG_CLONE_AUTH", "Warning: %s (%s@%s) authed to your account." },
- { "NSMSG_SETTING_LIST", "$b$N account settings:$b" },
+ { "NSMSG_SETTING_LIST", "$b$N account settings$b" },
+ { "NSMSG_SETTING_LIST_HEADER", "----------------------------------------" },
+ { "NSMSG_SETTING_LIST_END", "-------------End Of Settings------------" },
{ "NSMSG_INVALID_OPTION", "$b%s$b is an invalid account setting." },
{ "NSMSG_INVALID_ANNOUNCE", "$b%s$b is an invalid announcements value." },
{ "NSMSG_SET_INFO", "$bINFO: $b%s" },
{ "NSMSG_SET_PRIVMSG", "$bPRIVMSG: $b%s" },
{ "NSMSG_SET_STYLE", "$bSTYLE: $b%s" },
{ "NSMSG_SET_ANNOUNCEMENTS", "$bANNOUNCEMENTS: $b%s" },
+ { "NSMSG_SET_AUTOHIDE", "$bAUTOHIDE: $b%s" },
{ "NSMSG_SET_PASSWORD", "$bPASSWORD: $b%s" },
{ "NSMSG_SET_FLAGS", "$bFLAGS: $b%s" },
{ "NSMSG_SET_EMAIL", "$bEMAIL: $b%s" },
{ "NSMSG_SET_MAXLOGINS", "$bMAXLOGINS: $b%d" },
+ { "NSMSG_SET_ADVANCED", "$bADVANCED: $b%s" },
{ "NSMSG_SET_LANGUAGE", "$bLANGUAGE: $b%s" },
{ "NSMSG_SET_LEVEL", "$bLEVEL: $b%d" },
{ "NSMSG_SET_EPITHET", "$bEPITHET: $b%s" },
+ { "NSMSG_SET_NOTE", "$bNOTE: $b%s"},
{ "NSMSG_SET_TITLE", "$bTITLE: $b%s" },
{ "NSMSG_SET_FAKEHOST", "$bFAKEHOST: $b%s" },
+
+ { "NSMSG_AUTO_OPER", "You have been auto-opered" },
+ { "NSMSG_AUTO_OPER_ADMIN", "You have been auto-admined" },
+
{ "NSEMAIL_ACTIVATION_SUBJECT", "Account verification for %s" },
- { "NSEMAIL_ACTIVATION_BODY", "This email has been sent to verify that this email address belongs to the person who tried to register an account on %1$s. Your cookie is:\n %2$s\nTo verify your email address and complete the account registration, log on to %1$s and type the following command:\n /msg %3$s@%4$s COOKIE %5$s %2$s\nThis command is only used once to complete your account registration, and never again. Once you have run this command, you will need to authenticate everytime you reconnect to the network. To do this, you will have to type this command every time you reconnect:\n /msg %3$s@%4$s AUTH %5$s your-password\n Please remember to fill in 'your-password' with the actual password you gave to us when you registered.\n\nIf you did NOT request this account, you do not need to do anything. Please contact the %1$s staff if you have questions, and be sure to check our website." },
+ { "NSEMAIL_ACTIVATION_BODY",
+ "This email has been sent to verify that this email address belongs to the person who tried to register an account on %1$s. Your cookie is:\n"
+ "%2$s\n"
+ "To verify your email address and complete the account registration, log on to %1$s and type the following command:\n"
+ "/msg %3$s@%4$s COOKIE %5$s %2$s\n"
+ "This command is only used once to complete your account registration, and never again. Once you have run this command, you will need to authenticate everytime you reconnect to the network. To do this, you will have to type this command every time you reconnect:\n"
+ "/msg %3$s@%4$s AUTH %5$s your-password\n"
+ "(Please remember to fill in 'your-password' with the actual password you gave to us when you registered.)\n"
+ "OR configure Login-On-Connect (see http://www.afternet.org/login-on-connect for instructions) to connect pre-logged in every time.\n"
+ "\n"
+ "If you did NOT request this account, you do not need to do anything.\n"
+ "Please contact the %1$s staff if you have questions, and be sure to check our website." },
+ { "NSEMAIL_ACTIVATION_BODY_WEB",
+ "This email has been sent to verify that this email address belongs to the person who tried to register an account on %1$s. Your cookie is:\n"
+ "%2$s\n"
+ "To verify your email address and complete the account registration, visit the following URL:\n"
+ "http://www.afternet.org/index.php?option=com_registration&task=activate&username=%5$s&cookie=%2$s\n"
+ "\n"
+ "If you did NOT request this account, you do not need to do anything.\n"
+ "Please contact the %1$s staff if you have questions, and be sure to check our website." },
{ "NSEMAIL_PASSWORD_CHANGE_SUBJECT", "Password change verification on %s" },
- { "NSEMAIL_PASSWORD_CHANGE_BODY", "This email has been sent to verify that you wish to change the password on your account %5$s. Your cookie is %2$s.\nTo complete the password change, log on to %1$s and type the following command:\n /msg %3$s@%4$s COOKIE %5$s %2$s\nIf you did NOT request your password to be changed, you do not need to do anything. Please contact the %1$s staff if you have questions." },
+ { "NSEMAIL_PASSWORD_CHANGE_BODY",
+ "This email has been sent to verify that you wish to change the password on your account %5$s. Your cookie is %2$s.\n"
+ "To complete the password change, log on to %1$s and type the following command:\n"
+ "/msg %3$s@%4$s COOKIE %5$s %2$s\n"
+ "If you did NOT request your password to be changed, you do not need to do anything.\n"
+ "Please contact the %1$s staff if you have questions." },
+ { "NSEMAIL_PASSWORD_CHANGE_BODY_WEB",
+ "This email has been sent to verify that you wish to change the password on your account %5$s. Your cookie is %2$s.\n"
+ "To complete the password change, click the following URL:\n"
+ "http://www.afternet.org/index.php?option=com_registration&task=passcookie&username=%5$s&cookie=%2$s\n"
+ "If you did NOT request your password to be changed, you do not need to do anything.\n"
+ "Please contact the %1$s staff if you have questions." },
{ "NSEMAIL_EMAIL_CHANGE_SUBJECT", "Email address change verification for %s" },
+#ifdef stupid_verify_old_email
{ "NSEMAIL_EMAIL_CHANGE_BODY_NEW", "This email has been sent to verify that your email address belongs to the same person as account %5$s on %1$s. The SECOND HALF of your cookie is %2$.*6$s.\nTo verify your address as associated with this account, log on to %1$s and type the following command:\n /msg %3$s@%4$s COOKIE %5$s ?????%2$.*6$s\n(Replace the ????? with the FIRST HALF of the cookie, as sent to your OLD email address.)\nIf you did NOT request this email address to be associated with this account, you do not need to do anything. Please contact the %1$s staff if you have questions." },
{ "NSEMAIL_EMAIL_CHANGE_BODY_OLD", "This email has been sent to verify that you want to change your email for account %5$s on %1$s from this address to %7$s. The FIRST HALF of your cookie is %2$.*6$s\nTo verify your new address as associated with this account, log on to %1$s and type the following command:\n /msg %3$s@%4$s COOKIE %5$s %2$.*6$s?????\n(Replace the ????? with the SECOND HALF of the cookie, as sent to your NEW email address.)\nIf you did NOT request this change of email address, you do not need to do anything. Please contact the %1$s staff if you have questions." },
+#endif
{ "NSEMAIL_EMAIL_VERIFY_SUBJECT", "Email address verification for %s" },
{ "NSEMAIL_EMAIL_VERIFY_BODY", "This email has been sent to verify that this address belongs to the same person as %5$s on %1$s. Your cookie is %2$s.\nTo verify your address as associated with this account, log on to %1$s and type the following command:\n /msg %3$s@%4$s COOKIE %5$s %2$s\nIf you did NOT request this email address to be associated with this account, you do not need to do anything. Please contact the %1$s staff if you have questions." },
{ "NSEMAIL_ALLOWAUTH_SUBJECT", "Authentication allowed for %s" },
{ "NSEMAIL_ALLOWAUTH_BODY", "This email has been sent to let you authenticate (auth) to account %5$s on %1$s. Your cookie is %2$s.\nTo auth to that account, log on to %1$s and type the following command:\n /msg %3$s@%4$s COOKIE %5$s %2$s\nIf you did NOT request this authorization, you do not need to do anything. Please contact the %1$s staff if you have questions." },
+ { "NSMSG_NOT_VALID_FAKEHOST_DOT", "$b%s$b is not a valid vhost. (needs at least one dot)" },
+ { "NSMSG_NOT_VALID_FAKEHOST_AT", "$b%s$b is not a valid vhost. (it can not have a '@')" },
+ { "NSMSG_DENIED_FAKEHOST_WORD", "Access denied because there's a prohibited word in $b%s$b (%s)." },
+ { "NSMSG_NOT_VALID_FAKEHOST_LEN", "$b%s$b is not a valid vhost. (can only be 63 characters)" },
+ { "NSMSG_NOT_VALID_FAKEHOST_TLD_LEN", "$b%s$b is not a valid vhost. (TLD can only be 4 characters and less)" },
+ { "NSMSG_NOT_VALID_FAKEHOST_REGEX", "$b%s$b is not allowed by the admin, consult the valid vhost regex pattern in the config file under nickserv/valid_fakehost_regex." },
{ "CHECKPASS_YES", "Yes." },
{ "CHECKPASS_NO", "No." },
+ { "NSMSG_DEFCON_NO_NEW_NICKS", "You cannot register new %s at this time, please try again soon" },
{ NULL, NULL }
};
-enum reclaim_action {
- RECLAIM_NONE,
- RECLAIM_WARN,
- RECLAIM_SVSNICK,
- RECLAIM_KILL
-};
static void nickserv_reclaim(struct userNode *user, struct nick_info *ni, enum reclaim_action action);
static void nickserv_reclaim_p(void *data);
-static struct {
- unsigned int disable_nicks : 1;
- unsigned int valid_handle_regex_set : 1;
- unsigned int valid_nick_regex_set : 1;
- unsigned int autogag_enabled : 1;
- unsigned int email_enabled : 1;
- unsigned int email_required : 1;
- unsigned int default_hostmask : 1;
- unsigned int warn_nick_owned : 1;
- unsigned int warn_clone_auth : 1;
- unsigned long nicks_per_handle;
- unsigned long password_min_length;
- unsigned long password_min_digits;
- unsigned long password_min_upper;
- unsigned long password_min_lower;
- unsigned long db_backup_frequency;
- unsigned long handle_expire_frequency;
- unsigned long autogag_duration;
- unsigned long email_visible_level;
- unsigned long cookie_timeout;
- unsigned long handle_expire_delay;
- unsigned long nochan_handle_expire_delay;
- unsigned long modoper_level;
- unsigned long set_epithet_level;
- unsigned long set_title_level;
- unsigned long set_fakehost_level;
- unsigned long handles_per_email;
- unsigned long email_search_level;
- const char *network_name;
- const char *titlehost_suffix;
- regex_t valid_handle_regex;
- regex_t valid_nick_regex;
- dict_t weak_password_dict;
- struct policer_params *auth_policer_params;
- enum reclaim_action reclaim_action;
- enum reclaim_action auto_reclaim_action;
- unsigned long auto_reclaim_delay;
- unsigned char default_maxlogins;
- unsigned char hard_maxlogins;
-} nickserv_conf;
+struct nickserv_config nickserv_conf;
/* We have 2^32 unique account IDs to use. */
unsigned long int highest_id = 0;
return mask;
}
+static struct handle_note *
+nickserv_add_note(const char *setter, time_t date, const char *text)
+{
+ struct handle_note *note = calloc(1, sizeof(*note) + strlen(text));
+
+ strncpy(note->setter, setter, sizeof(note->setter)-1);
+ note->date = date;
+ memcpy(note->note, text, strlen(text));
+ return note;
+}
+
static struct handle_info *
register_handle(const char *handle, const char *passwd, UNUSED_ARG(unsigned long id))
{
struct handle_info *hi;
-#ifdef WITH_PROTOCOL_BAHAMUT
- char id_base64[IDLEN + 1];
- do
- {
- /* Assign a unique account ID to the account; note that 0 is
- an invalid account ID. 1 is therefore the first account ID. */
- if (!id) {
- id = 1 + highest_id++;
- } else {
- /* Note: highest_id is and must always be the highest ID. */
- if(id > highest_id) {
- highest_id = id;
- }
- }
- inttobase64(id_base64, id, IDLEN);
-
- /* Make sure an account with the same ID doesn't exist. If a
- duplicate is found, log some details and assign a new one.
- This should be impossible, but it never hurts to expect it. */
- if ((hi = dict_find(nickserv_id_dict, id_base64, NULL))) {
- log_module(NS_LOG, LOG_WARNING, "Duplicated account ID %lu (%s) found belonging to %s while inserting %s.", id, id_base64, hi->handle, handle);
- id = 0;
- }
- } while(!id);
-#endif
-
hi = calloc(1, sizeof(*hi));
- hi->userlist_style = HI_DEFAULT_STYLE;
+ hi->userlist_style = nickserv_conf.default_style ? nickserv_conf.default_style : HI_DEFAULT_STYLE;
hi->announcements = '?';
hi->handle = strdup(handle);
safestrncpy(hi->passwd, passwd, sizeof(hi->passwd));
hi->infoline = NULL;
dict_insert(nickserv_handle_dict, hi->handle, hi);
-#ifdef WITH_PROTOCOL_BAHAMUT
- hi->id = id;
- dict_insert(nickserv_id_dict, strdup(id_base64), hi);
-#endif
-
return hi;
}
dict_insert(nickserv_nick_dict, ni->nick, ni);
}
-static void
-free_nick_info(void *vni)
-{
- struct nick_info *ni = vni;
- free(ni);
-}
-
static void
delete_nick(struct nick_info *ni)
{
{
struct handle_info *hi = vhi;
-#ifdef WITH_PROTOCOL_BAHAMUT
- char id[IDLEN + 1];
-
- inttobase64(id, hi->id, IDLEN);
- dict_remove(nickserv_id_dict, id);
-#endif
-
free_string_list(hi->masks);
+ free_string_list(hi->ignores);
assert(!hi->users);
while (hi->nicks)
delete_nick(hi->nicks);
free(hi->infoline);
free(hi->epithet);
+ free(hi->note);
free(hi->fakehost);
if (hi->cookie) {
timeq_del(hi->cookie->expires, nickserv_free_cookie, hi->cookie, 0);
static void set_user_handle_info(struct userNode *user, struct handle_info *hi, int stamp);
-static void
-nickserv_unregister_handle(struct handle_info *hi, struct userNode *notify)
+static int
+nickserv_unregister_handle(struct handle_info *hi, struct userNode *notify, struct userNode *bot)
{
unsigned int n;
+ struct userNode *uNode;
+#ifdef WITH_LDAP
+ if(nickserv_conf.ldap_enable && nickserv_conf.ldap_admin_dn) {
+ int rc;
+ if(nickserv_conf.ldap_enable && nickserv_conf.ldap_admin_dn) {
+ if( (rc = ldap_delete_account(hi->handle)) != LDAP_SUCCESS) {
+ if(notify) {
+ send_message(notify, bot, "NSMSG_LDAP_FAIL", ldap_err2string(rc));
+ }
+ if(rc != LDAP_NO_SUCH_OBJECT)
+ return false; /* if theres noone there to delete, its kinda ok, right ?:) */
+ }
+ }
+ }
+#endif
for (n=0; n<unreg_func_used; n++)
unreg_func_list[n](notify, hi);
- while (hi->users)
+ while (hi->users) {
+ if (nickserv_conf.sync_log) {
+ uNode = GetUserH(hi->users->nick);
+ if (uNode)
+ irc_delete(uNode);
+ }
set_user_handle_info(hi->users, NULL, 0);
+ }
if (notify) {
if (nickserv_conf.disable_nicks)
- send_message(notify, nickserv, "NSMSG_UNREGISTER_SUCCESS", hi->handle);
+ send_message(notify, bot, "NSMSG_UNREGISTER_SUCCESS", hi->handle);
else
- send_message(notify, nickserv, "NSMSG_UNREGISTER_NICKS_SUCCESS", hi->handle);
+ send_message(notify, bot, "NSMSG_UNREGISTER_NICKS_SUCCESS", hi->handle);
}
+
+ if (nickserv_conf.sync_log)
+ SyncLog("UNREGISTER %s", hi->handle);
+
dict_remove(nickserv_handle_dict, hi->handle);
+ return true;
}
struct handle_info*
static int
is_registerable_nick(const char *nick)
{
- /* make sure it could be used as an account name */
- if (!is_valid_handle(nick))
+ struct userNode *user;
+ /* cant register a juped nick/service nick as nick, to prevent confusion */
+ user = GetUserH(nick);
+ if (user && IsLocal(user))
+ return 0;
+ /* for consistency, only allow nicks names that could be nicks */
+ if (!is_valid_nick(nick))
+ return 0;
+ /* disallow nicks that look like bad words */
+ if (opserv_bad_channel(nick))
return 0;
/* check length */
if (strlen(nick) > NICKLEN)
}
return 1;
}
+/* this has been replaced with one in tools.c
static int
is_valid_email_addr(const char *email)
return strchr(email, '@') != NULL;
}
+*/
+
static const char *
visible_email_addr(struct userNode *user, struct handle_info *hi)
{
}
int
-oper_outranks(struct userNode *user, struct handle_info *hi) {
+oper_outranks(struct svccmd *cmd, struct userNode *user, struct handle_info *hi) {
if (user->handle_info->opserv_level > hi->opserv_level)
return 1;
if (user->handle_info->opserv_level == hi->opserv_level) {
return 1;
}
}
- send_message(user, nickserv, "MSG_USER_OUTRANKED", hi->handle);
+ reply("MSG_USER_OUTRANKED", hi->handle);
return 0;
}
-static struct handle_info *
-get_victim_oper(struct userNode *user, const char *target)
+struct handle_info *
+get_victim_oper(struct svccmd *cmd, struct userNode *user, const char *target)
{
struct handle_info *hi;
if (!(hi = smart_get_handle_info(nickserv, user, target)))
send_message(user, nickserv, "MSG_OPER_SUSPENDED");
return 0;
}
- return oper_outranks(user, hi) ? hi : NULL;
+ return oper_outranks(cmd, user, hi) ? hi : NULL;
}
static int
{
unsigned int i, len;
unsigned int cnt_digits = 0, cnt_upper = 0, cnt_lower = 0;
+ int p;
+
len = strlen(pass);
if (len < nickserv_conf.password_min_length) {
if (user)
send_message(user, nickserv, "NSMSG_PASSWORD_ACCOUNT");
return 0;
}
- dict_find(nickserv_conf.weak_password_dict, pass, &i);
- if (i) {
+ dict_find(nickserv_conf.weak_password_dict, pass, &p);
+ if (p) {
if (user)
send_message(user, nickserv, "NSMSG_PASSWORD_DICTIONARY");
return 0;
static char *
generate_fakehost(struct handle_info *handle)
{
+ struct userNode *target;
extern const char *hidden_host_suffix;
static char buffer[HOSTLEN+1];
+ char *data;
+ int style = 1;
if (!handle->fakehost) {
- snprintf(buffer, sizeof(buffer), "%s.%s", handle->handle, hidden_host_suffix);
+ data = conf_get_data("server/hidden_host_type", RECDB_QSTRING);
+ if (data)
+ style = atoi(data);
+
+ if (style == 1)
+ snprintf(buffer, sizeof(buffer), "%s.%s", handle->handle, hidden_host_suffix);
+ else if (style == 2) {
+ /* Due to the way fakehost is coded theres no way i can
+ get the exact user, so for now ill just take the first
+ authed user. */
+ for (target = handle->users; target; target = target->next_authed)
+ break;
+
+ snprintf(buffer, sizeof(buffer), "%s", target->crypthost);
+ }
return buffer;
} else if (handle->fakehost[0] == '.') {
/* A leading dot indicates the stored value is actually a title. */
assign_fakehost(target, fake, 1);
}
+void send_func_list(struct userNode *user)
+{
+ unsigned int n;
+ struct handle_info *old_info;
+
+ old_info = user->handle_info;
+
+ for (n=0; n<auth_func_used; n++)
+ auth_func_list[n](user, old_info);
+}
+
static void
set_user_handle_info(struct userNode *user, struct handle_info *hi, int stamp)
{
user->handle_info = hi;
if (hi && !hi->users && !hi->opserv_level)
HANDLE_CLEAR_FLAG(hi, HELPING);
- for (n=0; n<auth_func_used; n++)
- auth_func_list[n](user, old_info);
+
+ /* Call auth handlers */
+ if (!GetUserH(user->nick))
+ user->loc = 1;
+
if (hi) {
struct nick_info *ni;
for (other = hi->users; other; other = other->next_authed)
send_message(other, nickserv, "NSMSG_CLONE_AUTH", user->nick, user->ident, user->hostname);
}
+
+ /* Add this auth to users list of current auths */
user->next_authed = hi->users;
hi->users = user;
hi->lastseen = now;
+ /* Add to helpers list */
if (IsHelper(user))
userList_append(&curr_helpers, user);
+ /* Set the fakehost */
if (hi->fakehost || old_info)
apply_fakehost(hi);
if (stamp) {
-#ifdef WITH_PROTOCOL_BAHAMUT
- /* Stamp users with their account ID. */
- char id[IDLEN + 1];
- inttobase64(id, hi->id, IDLEN);
-#elif WITH_PROTOCOL_P10
+#ifdef WITH_PROTOCOL_P10
/* Stamp users with their account name. */
char *id = hi->handle;
#else
const char *id = "???";
#endif
+ /* Mark all the nicks registered to this
+ * account as registered nicks
+ * - Why not just this one? -rubin */
if (!nickserv_conf.disable_nicks) {
struct nick_info *ni;
for (ni = hi->nicks; ni; ni = ni->next) {
}
}
}
- StampUser(user, id);
+ /* send the account to the ircd */
+ StampUser(user, id, hi->registered);
}
+ /* Stop trying to kick this user off their nick */
if ((ni = get_nick_info(user->nick)) && (ni->owner == hi))
timeq_del(0, nickserv_reclaim_p, user, TIMEQ_IGNORE_WHEN);
} else {
/* We cannot clear the user's account ID, unfortunately. */
user->next_authed = NULL;
}
+
+ /* Call auth handlers */
+ if (GetUserH(user->nick)) {
+ for (n=0; n<auth_func_used; n++)
+ auth_func_list[n](user, old_info);
+ }
}
static struct handle_info*
char crypted[MD5_CRYPT_LENGTH];
if ((hi = dict_find(nickserv_handle_dict, handle, NULL))) {
- send_message(user, nickserv, "NSMSG_HANDLE_EXISTS", handle);
+ if(user)
+ send_message(user, nickserv, "NSMSG_HANDLE_EXISTS", handle);
return 0;
}
+ if(strlen(handle) > 15)
+ {
+ if(user)
+ send_message(user, nickserv, "NSMSG_HANDLE_TOLONG", handle, 15);
+ return 0;
+ }
+
if (!is_secure_password(handle, passwd, user))
return 0;
cryptpass(passwd, crypted);
+#ifdef WITH_LDAP
+ if(nickserv_conf.ldap_enable && nickserv_conf.ldap_admin_dn) {
+ int rc;
+ rc = ldap_do_add(handle, crypted, NULL);
+ if(LDAP_SUCCESS != rc && LDAP_ALREADY_EXISTS != rc ) {
+ if(user)
+ send_message(user, nickserv, "NSMSG_LDAP_FAIL", ldap_err2string(rc));
+ return 0;
+ }
+ }
+#endif
hi = register_handle(handle, crypted, 0);
hi->masks = alloc_string_list(1);
+ hi->ignores = alloc_string_list(1);
hi->users = NULL;
hi->language = lang_C;
hi->registered = now;
if (settee && !no_auth)
set_user_handle_info(settee, hi, 1);
- if (user != settee)
+ if (user != settee) {
+ if(user)
send_message(user, nickserv, "NSMSG_OREGISTER_H_SUCCESS");
- else if (nickserv_conf.disable_nicks)
+ }
+ else if (nickserv_conf.disable_nicks) {
+ if(user) {
send_message(user, nickserv, "NSMSG_REGISTER_H_SUCCESS");
- else if ((ni = dict_find(nickserv_nick_dict, user->nick, NULL)))
+ }
+ }
+ else if ((ni = dict_find(nickserv_nick_dict, user->nick, NULL))) {
+ if(user) {
send_message(user, nickserv, "NSMSG_PARTIAL_REGISTER");
+ }
+ }
else {
- register_nick(user->nick, hi);
- send_message(user, nickserv, "NSMSG_REGISTER_HN_SUCCESS");
+ if(user) {
+ register_nick(user->nick, hi);
+ send_message(user, nickserv, "NSMSG_REGISTER_HN_SUCCESS");
+ }
}
- if (settee && (user != settee))
+ if (settee && (user != settee)) {
+ if(user) {
send_message(settee, nickserv, "NSMSG_OREGISTER_VICTIM", user->nick, hi->handle);
+ }
+ }
return hi;
}
timeq_add(cookie->expires, nickserv_free_cookie, cookie);
}
+/* Contributed by the great sneep of afternet ;) */
+/* Since this gets used in a URL, we want to avoid stuff that confuses
+ * email clients such as ] and ?. a-z, 0-9 only.
+ */
+void genpass(char *str, int len)
+{
+ int i = 0;
+ char c = 0;
+
+ for(i = 0; i < len; i++)
+ {
+ do
+ {
+ c = (char)((float)rand() / (float)RAND_MAX * (float)256);
+ } while(!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')));
+ str[i] = c;
+ }
+ str[i] = '\0';
+ return;
+}
+
static void
-nickserv_make_cookie(struct userNode *user, struct handle_info *hi, enum cookie_type type, const char *cookie_data)
+nickserv_make_cookie(struct userNode *user, struct handle_info *hi, enum cookie_type type, const char *cookie_data, int weblink)
{
struct handle_cookie *cookie;
char subject[128], body[4096], *misc;
cookie->hi = hi;
cookie->type = type;
cookie->data = cookie_data ? strdup(cookie_data) : NULL;
+
cookie->expires = now + nickserv_conf.cookie_timeout;
- inttobase64(cookie->cookie, rand(), 5);
- inttobase64(cookie->cookie+5, rand(), 5);
+ /* Adding dedicated password gen function for more control -Rubin */
+ genpass(cookie->cookie, 10);
+ /*
+ *inttobase64(cookie->cookie, rand(), 5);
+ *inttobase64(cookie->cookie+5, rand(), 5);
+ */
netname = nickserv_conf.network_name;
subject[0] = 0;
send_message(user, nickserv, "NSMSG_USE_COOKIE_REGISTER");
fmt = handle_find_message(hi, "NSEMAIL_ACTIVATION_SUBJECT");
snprintf(subject, sizeof(subject), fmt, netname);
- fmt = handle_find_message(hi, "NSEMAIL_ACTIVATION_BODY");
+
+ if(weblink)
+ fmt = handle_find_message(hi, "NSEMAIL_ACTIVATION_BODY_WEB");
+ else
+ fmt = handle_find_message(hi, "NSEMAIL_ACTIVATION_BODY");
+
snprintf(body, sizeof(body), fmt, netname, cookie->cookie, nickserv->nick, self->name, hi->handle);
first_time = 1;
break;
send_message(user, nickserv, "NSMSG_USE_COOKIE_RESETPASS");
fmt = handle_find_message(hi, "NSEMAIL_PASSWORD_CHANGE_SUBJECT");
snprintf(subject, sizeof(subject), fmt, netname);
- fmt = handle_find_message(hi, "NSEMAIL_PASSWORD_CHANGE_BODY");
+ if(weblink)
+ fmt = handle_find_message(hi, "NSEMAIL_PASSWORD_CHANGE_BODY_WEB");
+ else
+ fmt = handle_find_message(hi, "NSEMAIL_PASSWORD_CHANGE_BODY");
snprintf(body, sizeof(body), fmt, netname, cookie->cookie, nickserv->nick, self->name, hi->handle);
break;
case EMAIL_CHANGE:
misc = hi->email_addr;
hi->email_addr = cookie->data;
+#ifdef stupid_verify_old_email
if (misc) {
send_message(user, nickserv, "NSMSG_USE_COOKIE_EMAIL_2");
fmt = handle_find_message(hi, "NSEMAIL_EMAIL_CHANGE_SUBJECT");
fmt = handle_find_message(hi, "NSEMAIL_EMAIL_CHANGE_BODY_OLD");
snprintf(body, sizeof(body), fmt, netname, cookie->cookie, nickserv->nick, self->name, hi->handle, COOKIELEN/2, hi->email_addr);
} else {
+#endif
send_message(user, nickserv, "NSMSG_USE_COOKIE_EMAIL_1");
fmt = handle_find_message(hi, "NSEMAIL_EMAIL_VERIFY_SUBJECT");
snprintf(subject, sizeof(subject), fmt, netname);
snprintf(body, sizeof(body), fmt, netname, cookie->cookie, nickserv->nick, self->name, hi->handle);
sendmail(nickserv, hi, subject, body, 1);
subject[0] = 0;
+#ifdef stupid_verify_old_email
}
+#endif
hi->email_addr = misc;
break;
case ALLOWAUTH:
static NICKSERV_FUNC(cmd_register)
{
+ irc_in_addr_t ip;
struct handle_info *hi;
const char *email_addr, *password;
- int no_auth;
+ char syncpass[MD5_CRYPT_LENGTH];
+ int no_auth, weblink;
+
+ if (checkDefCon(DEFCON_NO_NEW_NICKS) && !IsOper(user)) {
+ reply("NSMSG_DEFCON_NO_NEW_NICKS", nickserv_conf.disable_nicks ? "accounts" : "nicknames");
+ return 0;
+ }
if (!IsOper(user) && !dict_size(nickserv_handle_dict)) {
/* Require the first handle registered to belong to someone +o. */
NICKSERV_MIN_PARMS((unsigned)3 + nickserv_conf.email_required);
+ if(nickserv_conf.force_handles_lowercase)
+ irc_strtolower(argv[1]);
if (!is_valid_handle(argv[1])) {
reply("NSMSG_BAD_HANDLE", argv[1]);
return 0;
}
+
if ((argc >= 4) && nickserv_conf.email_enabled) {
struct handle_info_list *hil;
const char *str;
email_addr = argv[3];
/* Check that the email address looks valid.. */
- if (!is_valid_email_addr(email_addr)) {
+ if (!valid_email(email_addr)) {
reply("NSMSG_BAD_EMAIL_ADDR");
return 0;
}
password = argv[2];
argv[2] = "****";
+ /* Webregister hack - send URL instead of IRC cookie
+ * commands in email
+ */
+ if((argc >= 5) && !strcmp(argv[4],"WEBLINK"))
+ weblink = 1;
+ else
+ weblink = 0;
if (!(hi = nickserv_register(user, user, argv[1], password, no_auth)))
return 0;
/* Add any masks they should get. */
string_list_append(hi->masks, strdup("*@*"));
} else {
string_list_append(hi->masks, generate_hostmask(user, GENMASK_OMITNICK|GENMASK_NO_HIDING|GENMASK_ANY_IDENT));
- if (user->ip.s_addr && user->hostname[strspn(user->hostname, "0123456789.")])
+ if (irc_in_addr_is_valid(user->ip) && !irc_pton(&ip, NULL, user->hostname))
string_list_append(hi->masks, generate_hostmask(user, GENMASK_OMITNICK|GENMASK_BYIP|GENMASK_NO_HIDING|GENMASK_ANY_IDENT));
}
}
/* Set their email address. */
- if (email_addr)
+ if (email_addr) {
+#ifdef WITH_LDAP
+ if(nickserv_conf.ldap_enable && nickserv_conf.ldap_admin_dn) {
+ int rc;
+ if((rc = ldap_do_modify(hi->handle, NULL, email_addr)) != LDAP_SUCCESS) {
+ /* Falied to update email in ldap, but still
+ * updated it here.. what should we do? */
+ reply("NSMSG_LDAP_FAIL_EMAIL", ldap_err2string(rc));
+ } else {
+ nickserv_set_email_addr(hi, email_addr);
+ }
+ }
+ else {
+ nickserv_set_email_addr(hi, email_addr);
+ }
+#else
nickserv_set_email_addr(hi, email_addr);
+#endif
+ }
/* If they need to do email verification, tell them. */
if (no_auth)
- nickserv_make_cookie(user, hi, ACTIVATION, hi->passwd);
+ nickserv_make_cookie(user, hi, ACTIVATION, hi->passwd, weblink);
/* Set registering flag.. */
user->modes |= FLAGS_REGISTERING;
+ if (nickserv_conf.sync_log) {
+ cryptpass(password, syncpass);
+ /*
+ * An 0 is only sent if theres no email address. Thios should only happen if email functions are
+ * disabled which they wont be for us. Email Required MUST be set on if you are using this.
+ * -SiRVulcaN
+ */
+ SyncLog("REGISTER %s %s %s %s", hi->handle, syncpass, email_addr ? email_addr : "0", user->info);
+ }
+
+ /* this wont work if email is required .. */
+ process_adduser_pending(user);
+
return 1;
}
static NICKSERV_FUNC(cmd_oregister)
{
- char *mask;
- struct userNode *settee;
+ struct userNode *settee = NULL;
struct handle_info *hi;
+ char* account = NULL;
+ char* pass = NULL;
+ char* email = NULL;
+ char* mask = NULL;
+ char* nick = NULL;
- NICKSERV_MIN_PARMS(4);
-
- if (!is_valid_handle(argv[1])) {
- reply("NSMSG_BAD_HANDLE", argv[1]);
- return 0;
+ NICKSERV_MIN_PARMS(3);
+
+ account = argv[1];
+ pass = argv[2];
+ if(nickserv_conf.force_handles_lowercase)
+ irc_strtolower(account);
+ if (nickserv_conf.email_required) {
+ NICKSERV_MIN_PARMS(4);
+ email = argv[3];
+ if (argc >= 5) {/* take: "acct pass email mask nick" or "acct pass email mask" or "acct pass email nick" */
+ if (strchr(argv[4], '@') || argc >= 6) /* If @, its mask not nick */
+ mask = argv[4];
+ else
+ nick = argv[4];
+ }
+ if (argc >= 6) {
+ nick = argv[5];
+ }
}
-
- if (strchr(argv[3], '@')) {
- mask = canonicalize_hostmask(strdup(argv[3]));
- if (argc > 4) {
- settee = GetUserH(argv[4]);
- if (!settee) {
- reply("MSG_NICK_UNKNOWN", argv[4]);
- free(mask);
- return 0;
- }
- } else {
- settee = NULL;
- }
- } else if ((settee = GetUserH(argv[3]))) {
- mask = generate_hostmask(settee, GENMASK_OMITNICK|GENMASK_NO_HIDING|GENMASK_ANY_IDENT);
- } else {
- reply("NSMSG_REGISTER_BAD_NICKMASK", argv[3]);
- return 0;
+ else {
+ if (argc >= 4) {/* take: "account pass mask nick" or "account pass mask" or "account pass nick" */
+ if (strchr(argv[3], '@') || argc >= 5) /* If @, its mask not nick */
+ mask = argv[3];
+ else
+ nick = argv[3];
+ }
+ if (argc >= 5) {
+ nick = argv[4];
+ }
}
+ /* If they passed a nick, look for that user.. */
+ if (nick && !(settee = GetUserH(nick))) {
+ reply("MSG_NICK_UNKNOWN", argv[4]);
+ return 0;
+ }
+ /* If the setee is already authed, we cant add a 2nd account for them.. */
if (settee && settee->handle_info) {
reply("NSMSG_USER_PREV_AUTH", settee->nick);
- free(mask);
return 0;
}
- if (!(hi = nickserv_register(user, settee, argv[1], argv[2], 0))) {
- free(mask);
- return 0;
+ /* If there is no default mask in the conf, and they didn't pass a mask,
+ * but we did find a user by nick, generate the mask */
+ if (!mask) {
+ if (nickserv_conf.default_hostmask)
+ mask = "*@*";
+ else if (settee)
+ mask = generate_hostmask(settee, GENMASK_OMITNICK|GENMASK_NO_HIDING|GENMASK_ANY_IDENT);
+ else {
+ reply("NSMSG_REGISTER_BAD_NICKMASK");
+ return 0;
+ }
+ }
+
+ if (!(hi = nickserv_register(user, settee, account, pass, 0))) {
+ return 0; /* error reply handled by above */
+ }
+ if (email) {
+#ifdef WITH_LDAP
+ if(nickserv_conf.ldap_enable && nickserv_conf.ldap_admin_dn) {
+ int rc;
+ if((rc = ldap_do_modify(hi->handle, NULL, email)) != LDAP_SUCCESS) {
+ /* Falied to update email in ldap, but still
+ * updated it here.. what should we do? */
+ reply("NSMSG_LDAP_FAIL_EMAIL", ldap_err2string(rc));
+ } else {
+ nickserv_set_email_addr(hi, email);
+ }
+ }
+ else {
+ nickserv_set_email_addr(hi, email);
+ }
+#else
+ nickserv_set_email_addr(hi, email);
+#endif
+ }
+ if (mask) {
+ char* mask_canonicalized = canonicalize_hostmask(strdup(mask));
+ string_list_append(hi->masks, mask_canonicalized);
+ }
+
+ if (nickserv_conf.sync_log)
+ SyncLog("REGISTER %s %s %s %s", hi->handle, hi->passwd, email ? email : "@", user->info); /* Send just @ for email if none */
+ return 1;
+}
+
+static int
+nickserv_ignore(struct svccmd *cmd, struct userNode *user, struct handle_info *hi, char *mask)
+{
+ unsigned int i;
+ struct userNode *target;
+ char *new_mask = strdup(pretty_mask(mask));
+ for (i=0; i<hi->ignores->used; i++) {
+ if (!irccasecmp(new_mask, hi->ignores->list[i])) {
+ reply("NSMSG_ADDIGNORE_ALREADY", new_mask);
+ free(new_mask);
+ return 0;
+ }
+ }
+ string_list_append(hi->ignores, new_mask);
+ reply("NSMSG_ADDIGNORE_SUCCESS", new_mask);
+
+ for (target = hi->users; target; target = target->next_authed) {
+ irc_silence(target, new_mask, 1);
}
- string_list_append(hi->masks, mask);
return 1;
}
+static NICKSERV_FUNC(cmd_addignore)
+{
+ NICKSERV_MIN_PARMS(2);
+
+ return nickserv_ignore(cmd, user, user->handle_info, argv[1]);
+}
+
+static NICKSERV_FUNC(cmd_oaddignore)
+{
+ struct handle_info *hi;
+
+ NICKSERV_MIN_PARMS(3);
+ if (!(hi = get_victim_oper(cmd, user, argv[1])))
+ return 0;
+
+ return nickserv_ignore(cmd, user, hi, argv[2]);
+}
+
+static int
+nickserv_delignore(struct svccmd *cmd, struct userNode *user, struct handle_info *hi, char *del_mask)
+{
+ unsigned int i;
+ struct userNode *target;
+ char *pmask = strdup(pretty_mask(del_mask));
+ for (i=0; i<hi->ignores->used; i++) {
+ if (!strcmp(pmask, hi->ignores->list[i]) || !strcmp(del_mask, hi->ignores->list[i])) {
+ char *old_mask = hi->ignores->list[i];
+ hi->ignores->list[i] = hi->ignores->list[--hi->ignores->used];
+ reply("NSMSG_DELMASK_SUCCESS", old_mask);
+ for (target = hi->users; target; target = target->next_authed) {
+ irc_silence(target, old_mask, 0);
+ }
+ free(old_mask);
+ free(pmask);
+ return 1;
+ }
+ }
+ reply("NSMSG_DELMASK_NOT_FOUND");
+ return 0;
+}
+
+static NICKSERV_FUNC(cmd_delignore)
+{
+ NICKSERV_MIN_PARMS(2);
+ return nickserv_delignore(cmd, user, user->handle_info, argv[1]);
+}
+
+static NICKSERV_FUNC(cmd_odelignore)
+{
+ struct handle_info *hi;
+ NICKSERV_MIN_PARMS(3);
+ if (!(hi = get_victim_oper(cmd, user, argv[1])))
+ return 0;
+ return nickserv_delignore(cmd, user, hi, argv[2]);
+}
+
static NICKSERV_FUNC(cmd_handleinfo)
{
char buff[400];
nsmsg_none = handle_find_message(hi, "MSG_NONE");
reply("NSMSG_HANDLEINFO_ON", hi->handle);
-#ifdef WITH_PROTOCOL_BAHAMUT
- reply("NSMSG_HANDLEINFO_ID", hi->id);
-#endif
+ reply("MSG_BAR");
reply("NSMSG_HANDLEINFO_REGGED", ctime(&hi->registered));
if (!hi->users) {
struct do_not_register *dnr;
if ((dnr = chanserv_is_dnr(NULL, hi)))
reply("NSMSG_HANDLEINFO_DNR", dnr->setter, dnr->reason);
- if (!oper_outranks(user, hi))
+ if (!oper_outranks(cmd, user, hi))
return 1;
- } else if (hi != user->handle_info)
+ } else if (hi != user->handle_info) {
+ reply("NSMSG_HANDLEINFO_END");
return 1;
+ }
if (nickserv_conf.email_enabled)
reply("NSMSG_HANDLEINFO_EMAIL_ADDR", visible_email_addr(user, hi));
reply("NSMSG_HANDLEINFO_EPITHET", (hi->epithet ? hi->epithet : nsmsg_none));
}
+ if (IsHelping(user) || IsOper(user))
+ {
+ if (hi->note)
+ {
+ char date[64];
+ strftime(date, 64, "%b %d %Y", localtime(&hi->note->date));
+ reply("NSMSG_HANDLEINFO_NOTE", hi->note->setter, date, hi->note->note);
+ }
+ }
+
if (hi->fakehost)
reply("NSMSG_HANDLEINFO_FAKEHOST", (hi->fakehost ? hi->fakehost : handle_find_message(hi, "MSG_NONE")));
reply("NSMSG_HANDLEINFO_MASKS", nsmsg_none);
}
+ if (hi->ignores->used) {
+ for (i=0; i < hi->ignores->used; i++) {
+ herelen = strlen(hi->ignores->list[i]);
+ if (pos + herelen + 1 > ArrayLength(buff)) {
+ i--;
+ goto print_ignore_buff;
+ }
+ memcpy(buff+pos, hi->ignores->list[i], herelen);
+ pos += herelen; buff[pos++] = ' ';
+ if (i+1 == hi->ignores->used) {
+ print_ignore_buff:
+ buff[pos-1] = 0;
+ reply("NSMSG_HANDLEINFO_IGNORES", buff);
+ pos = 0;
+ }
+ }
+ } else {
+ reply("NSMSG_HANDLEINFO_IGNORES", nsmsg_none);
+ }
+
if (hi->channels) {
struct userData *channel, *next;
char *name;
}
if (IsUserSuspended(channel))
buff[pos++] = '-';
- pos += sprintf(buff+pos, "%d:%s ", channel->access, name);
+ pos += sprintf(buff+pos, "%s:%s ", user_level_name_from_level(channel->access), name);
if (next == NULL) {
print_chans_buff:
buff[pos-1] = 0;
}
}
+ reply("NSMSG_HANDLEINFO_END");
return 1;
}
static NICKSERV_FUNC(cmd_rename_handle)
{
struct handle_info *hi;
- char msgbuf[MAXLEN], *old_handle;
+ struct userNode *uNode;
+ char *old_handle;
unsigned int nn;
NICKSERV_MIN_PARMS(3);
- if (!(hi = get_victim_oper(user, argv[1])))
+ if(nickserv_conf.force_handles_lowercase)
+ irc_strtolower(argv[2]);
+ if (!(hi = get_victim_oper(cmd, user, argv[1])))
return 0;
if (!is_valid_handle(argv[2])) {
reply("NSMSG_FAIL_RENAME", argv[1], argv[2]);
reply("NSMSG_HANDLE_EXISTS", argv[2]);
return 0;
}
+ if(strlen(argv[2]) > 15)
+ {
+ reply("NMSG_HANDLE_TOLONG", argv[2], 15);
+ return 0;
+ }
+#ifdef WITH_LDAP
+ if(nickserv_conf.ldap_enable && nickserv_conf.ldap_admin_dn) {
+ int rc;
+ if( (rc = ldap_rename_account(hi->handle, argv[2])) != LDAP_SUCCESS) {
+ reply("NSMSG_LDAP_FAIL", ldap_err2string(rc));
+ return 0;
+ }
+ }
+#endif
dict_remove2(nickserv_handle_dict, old_handle = hi->handle, 1);
hi->handle = strdup(argv[2]);
dict_insert(nickserv_handle_dict, hi->handle, hi);
for (nn=0; nn<rf_list_used; nn++)
rf_list[nn](hi, old_handle);
- snprintf(msgbuf, sizeof(msgbuf), "%s renamed account %s to %s.", user->handle_info->handle, old_handle, hi->handle);
+
+ if (nickserv_conf.sync_log) {
+ for (uNode = hi->users; uNode; uNode = uNode->next_authed)
+ irc_rename(uNode, hi->handle);
+
+ SyncLog("RENAME %s %s", old_handle, hi->handle);
+ }
+
reply("NSMSG_HANDLE_CHANGED", old_handle, hi->handle);
- global_message(MESSAGE_RECIPIENT_STAFF, msgbuf);
+ global_message_args(MESSAGE_RECIPIENT_OPERS, "NSMSG_ACCOUNT_RENAMED",
+ user->handle_info->handle, old_handle, hi->handle);
+
free(old_handle);
return 1;
}
failpw_func_list[failpw_func_used++] = func;
}
+/*
+ * Return hi if the handle/pass pair matches, NULL if it doesnt.
+ *
+ * called by nefariouses enhanced AC login-on-connect code
+ *
+ */
+struct handle_info *loc_auth(char *handle, char *password)
+{
+ int pw_arg, used, maxlogins;
+ unsigned int ii;
+ int wildmask = 0;
+ struct handle_info *hi;
+ struct userNode *other;
+#ifdef WITH_LDAP
+ int ldap_result = LDAP_SUCCESS;
+ char *email = NULL;
+
+#endif
+
+ hi = dict_find(nickserv_handle_dict, handle, NULL);
+ pw_arg = 2;
+
+#ifdef WITH_LDAP
+ if(nickserv_conf.ldap_enable) {
+ ldap_result = ldap_check_auth(handle, password);
+ if(ldap_result != LDAP_SUCCESS) {
+ return NULL;
+ }
+ }
+// else
+#else
+ if (!checkpass(password, hi->passwd)) {
+ return NULL;
+ }
+#endif
+#ifdef WITH_LDAP
+ if( (!hi) && nickserv_conf.ldap_enable && ldap_result == LDAP_SUCCESS && nickserv_conf.ldap_autocreate) {
+ /* user not found, but authed to ldap successfully..
+ * create the account.
+ */
+ char *mask;
+ int rc;
+
+ /* Add a *@* mask */
+ if(nickserv_conf.default_hostmask)
+ mask = "*@*";
+ else
+ return NULL; /* They dont have a *@* mask so they can't loc */
+
+ if(!(hi = nickserv_register(NULL, NULL, handle, password, 0))) {
+ return 0; /* couldn't add the user for some reason */
+ }
+
+ if((rc = ldap_get_user_info(handle, &email) != LDAP_SUCCESS))
+ {
+ if(nickserv_conf.email_required) {
+ return 0;
+ }
+ }
+ if(email) {
+ nickserv_set_email_addr(hi, email);
+ free(email);
+ }
+ if(mask) {
+ char* mask_canonicalized = canonicalize_hostmask(strdup(mask));
+ string_list_append(hi->masks, mask_canonicalized);
+ }
+ if(nickserv_conf.sync_log)
+ SyncLog("REGISTER %s %s %s %s", hi->handle, hi->passwd, "@", handle);
+ }
+#endif
+
+ /* Still no account, so just fail out */
+ if (!hi) {
+ return NULL;
+ }
+
+ /* We don't know the users hostname, or anything because they
+ * havn't registered yet. So we can only allow LOC if your
+ * account has *@* as a hostmask.
+ */
+ for (ii=0; ii<hi->masks->used; ii++)
+ {
+ if (!strcmp(hi->masks->list[ii], "*@*"))
+ {
+ wildmask++;
+ break;
+ }
+ }
+ if(wildmask < 1)
+ return NULL;
+
+ if (HANDLE_FLAGGED(hi, SUSPENDED)) {
+ return NULL;
+ }
+
+ maxlogins = hi->maxlogins ? hi->maxlogins : nickserv_conf.default_maxlogins;
+ for (used = 0, other = hi->users; other; other = other->next_authed) {
+ if (++used >= maxlogins) {
+ return NULL;
+ }
+ }
+ /* TODO - Add LOGGING to this function so LOC's are logged.. */
+ return hi;
+}
+
static NICKSERV_FUNC(cmd_auth)
{
int pw_arg, used, maxlogins;
struct handle_info *hi;
const char *passwd;
struct userNode *other;
+#ifdef WITH_LDAP
+ int ldap_result = LDAP_OTHER;
+ char *email = NULL;
+#endif
if (user->handle_info) {
reply("NSMSG_ALREADY_AUTHED", user->handle_info->handle);
return 0;
}
if (argc == 3) {
+#ifdef WITH_LDAP
+ if(strchr(argv[1], '<') || strchr(argv[1], '>')) {
+ reply("NSMSG_NO_ANGLEBRACKETS");
+ return 0;
+ }
+ if (!is_valid_handle(argv[1])) {
+ reply("NSMSG_BAD_HANDLE", argv[1]);
+ return 0;
+ }
+
+ if(nickserv_conf.ldap_enable) {
+ ldap_result = ldap_check_auth(argv[1], argv[2]);
+ /* Get the users email address and update it */
+ if(ldap_result == LDAP_SUCCESS) {
+ int rc;
+ if((rc = ldap_get_user_info(argv[1], &email) != LDAP_SUCCESS))
+ {
+ if(nickserv_conf.email_required) {
+ reply("NSMSG_LDAP_FAIL_GET_EMAIL", ldap_err2string(rc));
+ return 0;
+ }
+ }
+ }
+ else if(ldap_result != LDAP_INVALID_CREDENTIALS) {
+ reply("NSMSG_LDAP_FAIL", ldap_err2string(ldap_result));
+ return 0;
+ }
+ }
+
+#endif
hi = dict_find(nickserv_handle_dict, argv[1], NULL);
pw_arg = 2;
} else if (argc == 2) {
}
} else {
/* try to look up their handle from their nick */
+ /* TODO: handle ldap auth on nickserv style networks, too */
struct nick_info *ni;
ni = get_nick_info(user->nick);
if (!ni) {
pw_arg = 1;
} else {
reply("MSG_MISSING_PARAMS", argv[0]);
- svccmd_send_help(user, nickserv, cmd);
+ svccmd_send_help_brief(user, nickserv, cmd);
return 0;
}
if (!hi) {
- reply("NSMSG_HANDLE_NOT_FOUND");
- return 0;
+#ifdef WITH_LDAP
+ if(nickserv_conf.ldap_enable && ldap_result == LDAP_SUCCESS && nickserv_conf.ldap_autocreate) {
+ /* user not found, but authed to ldap successfully..
+ * create the account.
+ */
+ char *mask;
+ if(!(hi = nickserv_register(user, NULL, argv[1], argv[2], 0))) {
+ reply("NSMSG_UNABLE_TO_ADD");
+ return 0; /* couldn't add the user for some reason */
+ }
+ /* Add a *@* mask */
+ if(nickserv_conf.default_hostmask)
+ mask = "*@*";
+ else
+ mask = generate_hostmask(user, GENMASK_OMITNICK|GENMASK_NO_HIDING|GENMASK_ANY_IDENT);
+
+ if(mask) {
+ char* mask_canonicalized = canonicalize_hostmask(strdup(mask));
+ string_list_append(hi->masks, mask_canonicalized);
+ }
+ if(email) {
+ nickserv_set_email_addr(hi, email);
+ free(email);
+ }
+ if(nickserv_conf.sync_log)
+ SyncLog("REGISTER %s %s %s %s", hi->handle, hi->passwd, email ? email : "@", user->info);
+ }
+ else {
+#endif
+ reply("NSMSG_HANDLE_NOT_FOUND");
+ return 0;
+#ifdef WITH_LDAP
+ }
+#endif
}
/* Responses from here on look up the language used by the handle they asked about. */
passwd = argv[pw_arg];
argv[pw_arg] = "BADMASK";
return 1;
}
+#ifdef WITH_LDAP
+ if( ( nickserv_conf.ldap_enable && ldap_result == LDAP_INVALID_CREDENTIALS ) ||
+ ( !nickserv_conf.ldap_enable && !checkpass(passwd, hi->passwd) ) ) {
+#else
if (!checkpass(passwd, hi->passwd)) {
+#endif
unsigned int n;
send_message_type(4, user, cmd->parent->bot,
handle_find_message(hi, "NSMSG_PASSWORD_INVALID"));
reply("NSMSG_WEAK_PASSWORD");
if (hi->passwd[0] != '$')
cryptpass(passwd, hi->passwd);
+
+ /* If a channel was waiting for this user to auth,
+ * finish adding them */
+ process_adduser_pending(user);
+
reply("NSMSG_AUTH_SUCCESS");
+
+
+ /* Set +x if autohide is on */
+ if(HANDLE_FLAGGED(hi, AUTOHIDE))
+ irc_umode(user, "+x");
+
+ if(!IsOper(user)) /* If they arnt already opered.. */
+ {
+ /* Auto Oper users with Opserv access -Life4Christ 8-10-2005 */
+ if( nickserv_conf.auto_admin[0] && hi->opserv_level >= opserv_conf_admin_level())
+ {
+ irc_umode(user,nickserv_conf.auto_admin);
+ reply("NSMSG_AUTO_OPER_ADMIN");
+ }
+ else if (nickserv_conf.auto_oper[0] && hi->opserv_level > 0)
+ {
+ irc_umode(user,nickserv_conf.auto_oper);
+ reply("NSMSG_AUTO_OPER");
+ }
+ }
+
+ /* Wipe out the pass for the logs */
argv[pw_arg] = "****";
return 1;
}
reply("MSG_SET_EMAIL_ADDR");
return 0;
}
- nickserv_make_cookie(user, hi, ALLOWAUTH, NULL);
+ nickserv_make_cookie(user, hi, ALLOWAUTH, NULL, 0);
+ return 1;
+}
+
+static NICKSERV_FUNC(cmd_delcookie)
+{
+ struct handle_info *hi;
+
+ hi = user->handle_info;
+ if (!hi->cookie) {
+ reply("NSMSG_NO_COOKIE");
+ return 0;
+ }
+ switch (hi->cookie->type) {
+ case ACTIVATION:
+ case EMAIL_CHANGE:
+ reply("NSMSG_MUST_TIME_OUT");
+ break;
+ default:
+ nickserv_eat_cookie(hi->cookie);
+ reply("NSMSG_ATE_COOKIE");
+ break;
+ }
return 1;
}
-static NICKSERV_FUNC(cmd_delcookie)
+static NICKSERV_FUNC(cmd_odelcookie)
{
struct handle_info *hi;
- hi = user->handle_info;
+ NICKSERV_MIN_PARMS(2);
+
+ if (!(hi = get_victim_oper(cmd, user, argv[1])))
+ return 0;
+
if (!hi->cookie) {
- reply("NSMSG_NO_COOKIE");
+ reply("NSMSG_NO_COOKIE_FOREIGN", hi->handle);
return 0;
}
+
switch (hi->cookie->type) {
case ACTIVATION:
+ safestrncpy(hi->passwd, hi->cookie->data, sizeof(hi->passwd));
+ if (nickserv_conf.sync_log)
+ SyncLog("ACCOUNTACC %s", hi->handle);
+ break;
+ case PASSWORD_CHANGE:
+ safestrncpy(hi->passwd, hi->cookie->data, sizeof(hi->passwd));
+ if (nickserv_conf.sync_log)
+ SyncLog("PASSCHANGE %s %s", hi->handle, hi->passwd);
+ break;
case EMAIL_CHANGE:
- reply("NSMSG_MUST_TIME_OUT");
+ if (!hi->email_addr && nickserv_conf.sync_log) {
+ if (nickserv_conf.sync_log)
+ SyncLog("REGISTER %s %s %s %s", hi->handle, hi->passwd, hi->cookie->data, user->info);
+ }
+#ifdef WITH_LDAP
+ if(nickserv_conf.ldap_enable && nickserv_conf.ldap_admin_dn) {
+ int rc;
+ if((rc = ldap_do_modify(hi->handle, NULL, hi->cookie->data)) != LDAP_SUCCESS) {
+ /* Falied to update email in ldap, but still
+ * updated it here.. what should we do? */
+ reply("NSMSG_LDAP_FAIL_SEND_EMAIL", ldap_err2string(rc));
+ } else {
+ nickserv_set_email_addr(hi, hi->cookie->data);
+ }
+ }
+ else {
+ nickserv_set_email_addr(hi, hi->cookie->data);
+ }
+#else
+ nickserv_set_email_addr(hi, hi->cookie->data);
+#endif
+ if (nickserv_conf.sync_log)
+ SyncLog("EMAILCHANGE %s %s", hi->handle, hi->cookie->data);
break;
default:
- nickserv_eat_cookie(hi->cookie);
- reply("NSMSG_ATE_COOKIE");
+ reply("NSMSG_BAD_COOKIE_TYPE", hi->cookie->type);
+ log_module(NS_LOG, LOG_ERROR, "Bad cookie type %d for account %s.", hi->cookie->type, hi->handle);
break;
}
+
+ nickserv_eat_cookie(hi->cookie);
+ reply("NSMSG_ATE_FOREIGN_COOKIE", hi->handle);
+
return 1;
}
{
struct handle_info *hi;
char crypted[MD5_CRYPT_LENGTH];
+ int weblink;
NICKSERV_MIN_PARMS(3);
+ if(argc >= 4 && !strcmp(argv[3], "WEBLINK"))
+ weblink = 1;
+ else
+ weblink = 0;
if (user->handle_info) {
reply("NSMSG_ALREADY_AUTHED", user->handle_info->handle);
return 0;
}
cryptpass(argv[2], crypted);
argv[2] = "****";
- nickserv_make_cookie(user, hi, PASSWORD_CHANGE, crypted);
+ nickserv_make_cookie(user, hi, PASSWORD_CHANGE, crypted, weblink);
return 1;
}
switch (hi->cookie->type) {
case ACTIVATION:
+#ifdef WITH_LDAP
+ if(nickserv_conf.ldap_enable && nickserv_conf.ldap_admin_dn) {
+ int rc;
+ if((rc = ldap_do_modify(hi->handle, hi->cookie->data, NULL)) != LDAP_SUCCESS) {
+ /* Falied to update email in ldap, but still
+ * updated it here.. what should we do? */
+ reply("NSMSG_LDAP_FAIL", ldap_err2string(rc));
+ return 0;
+ }
+ }
+#endif
safestrncpy(hi->passwd, hi->cookie->data, sizeof(hi->passwd));
set_user_handle_info(user, hi, 1);
reply("NSMSG_HANDLE_ACTIVATED");
+ if (nickserv_conf.sync_log)
+ SyncLog("ACCOUNTACC %s", hi->handle);
break;
case PASSWORD_CHANGE:
+#ifdef WITH_LDAP
+ if(nickserv_conf.ldap_enable && nickserv_conf.ldap_admin_dn) {
+ int rc;
+ if((rc = ldap_do_modify(hi->handle, hi->cookie->data, NULL)) != LDAP_SUCCESS) {
+ /* Falied to update email in ldap, but still
+ * updated it here.. what should we do? */
+ reply("NSMSG_LDAP_FAIL", ldap_err2string(rc));
+ return 0;
+ }
+ }
+#endif
set_user_handle_info(user, hi, 1);
safestrncpy(hi->passwd, hi->cookie->data, sizeof(hi->passwd));
reply("NSMSG_PASSWORD_CHANGED");
+ if (nickserv_conf.sync_log)
+ SyncLog("PASSCHANGE %s %s", hi->handle, hi->passwd);
break;
case EMAIL_CHANGE:
+#ifdef WITH_LDAP
+ if(nickserv_conf.ldap_enable && nickserv_conf.ldap_admin_dn) {
+ int rc;
+ if((rc = ldap_do_modify(hi->handle, NULL, hi->cookie->data)) != LDAP_SUCCESS) {
+ /* Falied to update email in ldap, but still
+ * updated it here.. what should we do? */
+ reply("NSMSG_LDAP_FAIL_SEND_EMAIL", ldap_err2string(rc));
+ return 0;
+ }
+ }
+#endif
+ if (!hi->email_addr && nickserv_conf.sync_log) {
+ /*
+ * This should only happen if an OREGISTER was sent. Require
+ * email must be enabled! - SiRVulcaN
+ */
+ if (nickserv_conf.sync_log)
+ SyncLog("REGISTER %s %s %s %s", hi->handle, hi->passwd, hi->cookie->data, user->info);
+ }
+
nickserv_set_email_addr(hi, hi->cookie->data);
reply("NSMSG_EMAIL_CHANGED");
+ if (nickserv_conf.sync_log)
+ SyncLog("EMAILCHANGE %s %s", hi->handle, hi->cookie->data);
break;
case ALLOWAUTH:
set_user_handle_info(user, hi, 1);
nickserv_eat_cookie(hi->cookie);
+ process_adduser_pending(user);
+
return 1;
}
static NICKSERV_FUNC(cmd_pass)
{
struct handle_info *hi;
- const char *old_pass, *new_pass;
+ char *old_pass, *new_pass;
+ char crypted[MD5_CRYPT_LENGTH+1];
+#ifdef WITH_LDAP
+ int ldap_result;
+#endif
NICKSERV_MIN_PARMS(3);
hi = user->handle_info;
new_pass = argv[2];
argv[2] = "****";
if (!is_secure_password(hi->handle, new_pass, user)) return 0;
+
+#ifdef WITH_LDAP
+ if(nickserv_conf.ldap_enable) {
+ ldap_result = ldap_check_auth(hi->handle, old_pass);
+ if(ldap_result != LDAP_SUCCESS) {
+ if(ldap_result == LDAP_INVALID_CREDENTIALS)
+ reply("NSMSG_PASSWORD_INVALID");
+ else
+ reply("NSMSG_LDAP_FAIL", ldap_err2string(ldap_result));
+ return 0;
+ }
+ }else
+#endif
if (!checkpass(old_pass, hi->passwd)) {
argv[1] = "BADPASS";
reply("NSMSG_PASSWORD_INVALID");
return 0;
}
- cryptpass(new_pass, hi->passwd);
+ cryptpass(new_pass, crypted);
+#ifdef WITH_LDAP
+ if(nickserv_conf.ldap_enable && nickserv_conf.ldap_admin_dn) {
+ int rc;
+ if((rc = ldap_do_modify(hi->handle, crypted, NULL)) != LDAP_SUCCESS) {
+ reply("NSMSG_LDAP_FAIL", ldap_err2string(rc));
+ return 0;
+ }
+ }
+#endif
+ //cryptpass(new_pass, hi->passwd);
+ strcpy(hi->passwd, crypted);
+ if (nickserv_conf.sync_log)
+ SyncLog("PASSCHANGE %s %s", hi->handle, hi->passwd);
argv[1] = "****";
reply("NSMSG_PASS_SUCCESS");
return 1;
}
static int
-nickserv_addmask(struct userNode *user, struct handle_info *hi, const char *mask)
+nickserv_addmask(struct svccmd *cmd, struct userNode *user, struct handle_info *hi, const char *mask)
{
unsigned int i;
char *new_mask = canonicalize_hostmask(strdup(mask));
for (i=0; i<hi->masks->used; i++) {
if (!irccasecmp(new_mask, hi->masks->list[i])) {
- send_message(user, nickserv, "NSMSG_ADDMASK_ALREADY", new_mask);
+ reply("NSMSG_ADDMASK_ALREADY", new_mask);
free(new_mask);
return 0;
}
}
string_list_append(hi->masks, new_mask);
- send_message(user, nickserv, "NSMSG_ADDMASK_SUCCESS", new_mask);
+ reply("NSMSG_ADDMASK_SUCCESS", new_mask);
return 1;
}
{
if (argc < 2) {
char *mask = generate_hostmask(user, GENMASK_OMITNICK|GENMASK_NO_HIDING|GENMASK_ANY_IDENT);
- int res = nickserv_addmask(user, user->handle_info, mask);
+ int res = nickserv_addmask(cmd, user, user->handle_info, mask);
free(mask);
return res;
} else {
reply("NSMSG_MASK_INVALID", argv[1]);
return 0;
}
- return nickserv_addmask(user, user->handle_info, argv[1]);
+ return nickserv_addmask(cmd, user, user->handle_info, argv[1]);
}
}
struct handle_info *hi;
NICKSERV_MIN_PARMS(3);
- if (!(hi = get_victim_oper(user, argv[1])))
+ if (!(hi = get_victim_oper(cmd, user, argv[1])))
return 0;
- return nickserv_addmask(user, hi, argv[2]);
+ return nickserv_addmask(cmd, user, hi, argv[2]);
}
static int
-nickserv_delmask(struct userNode *user, struct handle_info *hi, const char *del_mask)
+nickserv_delmask(struct svccmd *cmd, struct userNode *user, struct handle_info *hi, const char *del_mask)
{
unsigned int i;
for (i=0; i<hi->masks->used; i++) {
if (!strcmp(del_mask, hi->masks->list[i])) {
char *old_mask = hi->masks->list[i];
if (hi->masks->used == 1) {
- send_message(user, nickserv, "NSMSG_DELMASK_NOTLAST");
+ reply("NSMSG_DELMASK_NOTLAST");
return 0;
}
hi->masks->list[i] = hi->masks->list[--hi->masks->used];
- send_message(user, nickserv, "NSMSG_DELMASK_SUCCESS", old_mask);
+ reply("NSMSG_DELMASK_SUCCESS", old_mask);
free(old_mask);
return 1;
}
}
- send_message(user, nickserv, "NSMSG_DELMASK_NOT_FOUND");
+ reply("NSMSG_DELMASK_NOT_FOUND");
return 0;
}
static NICKSERV_FUNC(cmd_delmask)
{
NICKSERV_MIN_PARMS(2);
- return nickserv_delmask(user, user->handle_info, argv[1]);
+ return nickserv_delmask(cmd, user, user->handle_info, argv[1]);
}
static NICKSERV_FUNC(cmd_odelmask)
{
struct handle_info *hi;
NICKSERV_MIN_PARMS(3);
- if (!(hi = get_victim_oper(user, argv[1])))
+ if (!(hi = get_victim_oper(cmd, user, argv[1])))
return 0;
- return nickserv_delmask(user, hi, argv[2]);
+ return nickserv_delmask(cmd, user, hi, argv[2]);
}
int
}
static void
-set_list(struct userNode *user, struct handle_info *hi, int override)
+set_list(struct svccmd *cmd, struct userNode *user, struct handle_info *hi, int override)
{
option_func_t *opt;
unsigned int i;
char *set_display[] = {
"INFO", "WIDTH", "TABLEWIDTH", "COLOR", "PRIVMSG", "STYLE",
- "EMAIL", "ANNOUNCEMENTS", "MAXLOGINS", "LANGUAGE"
+ "EMAIL", "ANNOUNCEMENTS", "AUTOHIDE", "MAXLOGINS", "LANGUAGE",
+ "FAKEHOST", "TITLE", "EPITHET", "ADVANCED"
};
- send_message(user, nickserv, "NSMSG_SETTING_LIST");
+ reply("NSMSG_SETTING_LIST");
+ reply("NSMSG_SETTING_LIST_HEADER");
/* Do this so options are presented in a consistent order. */
for (i = 0; i < ArrayLength(set_display); ++i)
if ((opt = dict_find(nickserv_opt_dict, set_display[i], NULL)))
- opt(user, hi, override, 0, NULL);
+ opt(cmd, user, hi, override, 0, NULL);
+ reply("NSMSG_SETTING_LIST_END");
}
static NICKSERV_FUNC(cmd_set)
hi = user->handle_info;
if (argc < 2) {
- set_list(user, hi, 0);
+ set_list(cmd, user, hi, 0);
return 1;
}
if (!(opt = dict_find(nickserv_opt_dict, argv[1], NULL))) {
reply("NSMSG_INVALID_OPTION", argv[1]);
return 0;
}
- return opt(user, hi, 0, argc-1, argv+1);
+ return opt(cmd, user, hi, 0, argc-1, argv+1);
}
static NICKSERV_FUNC(cmd_oset)
NICKSERV_MIN_PARMS(2);
- if (!(hi = get_victim_oper(user, argv[1])))
+ if (!(hi = get_victim_oper(cmd, user, argv[1])))
return 0;
if (argc < 3) {
- set_list(user, hi, 0);
+ set_list(cmd, user, hi, 0);
return 1;
}
return 0;
}
- return opt(user, hi, 1, argc-2, argv+2);
+ return opt(cmd, user, hi, 1, argc-2, argv+2);
}
static OPTION_FUNC(opt_info)
}
info = hi->infoline ? hi->infoline : user_find_message(user, "MSG_NONE");
- send_message(user, nickserv, "NSMSG_SET_INFO", info);
+ reply("NSMSG_SET_INFO", info);
return 1;
}
else if (hi->screen_width > MAX_LINE_SIZE)
hi->screen_width = MAX_LINE_SIZE;
- send_message(user, nickserv, "NSMSG_SET_WIDTH", hi->screen_width);
+ reply("NSMSG_SET_WIDTH", hi->screen_width);
return 1;
}
else if (hi->screen_width > MAX_LINE_SIZE)
hi->table_width = MAX_LINE_SIZE;
- send_message(user, nickserv, "NSMSG_SET_TABLEWIDTH", hi->table_width);
+ reply("NSMSG_SET_TABLEWIDTH", hi->table_width);
return 1;
}
else if (disabled_string(argv[1]))
HANDLE_CLEAR_FLAG(hi, MIRC_COLOR);
else {
- send_message(user, nickserv, "MSG_INVALID_BINARY", argv[1]);
+ reply("MSG_INVALID_BINARY", argv[1]);
return 0;
}
}
- send_message(user, nickserv, "NSMSG_SET_COLOR", user_find_message(user, HANDLE_FLAGGED(hi, MIRC_COLOR) ? "MSG_ON" : "MSG_OFF"));
+ reply("NSMSG_SET_COLOR", user_find_message(user, HANDLE_FLAGGED(hi, MIRC_COLOR) ? "MSG_ON" : "MSG_OFF"));
return 1;
}
else if (disabled_string(argv[1]))
HANDLE_CLEAR_FLAG(hi, USE_PRIVMSG);
else {
- send_message(user, nickserv, "MSG_INVALID_BINARY", argv[1]);
+ reply("MSG_INVALID_BINARY", argv[1]);
+ return 0;
+ }
+ }
+
+ reply("NSMSG_SET_PRIVMSG", user_find_message(user, HANDLE_FLAGGED(hi, USE_PRIVMSG) ? "MSG_ON" : "MSG_OFF"));
+ return 1;
+}
+
+static OPTION_FUNC(opt_autohide)
+{
+ if (argc > 1) {
+ if (enabled_string(argv[1]))
+ HANDLE_SET_FLAG(hi, AUTOHIDE);
+ else if (disabled_string(argv[1]))
+ HANDLE_CLEAR_FLAG(hi, AUTOHIDE);
+ else {
+ reply("MSG_INVALID_BINARY", argv[1]);
return 0;
}
}
- send_message(user, nickserv, "NSMSG_SET_PRIVMSG", user_find_message(user, HANDLE_FLAGGED(hi, USE_PRIVMSG) ? "MSG_ON" : "MSG_OFF"));
+ reply("NSMSG_SET_AUTOHIDE", user_find_message(user, HANDLE_FLAGGED(hi, AUTOHIDE) ? "MSG_ON" : "MSG_OFF"));
return 1;
}
char *style;
if (argc > 1) {
- if (!irccasecmp(argv[1], "Zoot"))
- hi->userlist_style = HI_STYLE_ZOOT;
- else if (!irccasecmp(argv[1], "def"))
- hi->userlist_style = HI_STYLE_DEF;
- }
+ if (!irccasecmp(argv[1], "Clean"))
+ hi->userlist_style = HI_STYLE_CLEAN;
+ else if (!irccasecmp(argv[1], "Advanced"))
+ hi->userlist_style = HI_STYLE_ADVANCED;
+ else if (!irccasecmp(argv[1], "Classic"))
+ hi->userlist_style = HI_STYLE_CLASSIC;
+ else /* Default to normal */
+ hi->userlist_style = HI_STYLE_NORMAL;
+ } /* TODO: give error if unknow style is chosen */
switch (hi->userlist_style) {
- case HI_STYLE_DEF:
- style = "def";
- break;
- case HI_STYLE_ZOOT:
- default:
- style = "Zoot";
- }
-
- send_message(user, nickserv, "NSMSG_SET_STYLE", style);
+ case HI_STYLE_ADVANCED:
+ style = "Advanced";
+ break;
+ case HI_STYLE_CLASSIC:
+ style = "Classic";
+ break;
+ case HI_STYLE_CLEAN:
+ style = "Clean";
+ break;
+ case HI_STYLE_NORMAL:
+ default:
+ style = "Normal";
+ }
+
+ reply("NSMSG_SET_STYLE", style);
return 1;
}
else if (!strcmp(argv[1], "?") || !irccasecmp(argv[1], "default"))
hi->announcements = '?';
else {
- send_message(user, nickserv, "NSMSG_INVALID_ANNOUNCE", argv[1]);
+ reply("NSMSG_INVALID_ANNOUNCE", argv[1]);
return 0;
}
}
case '?': choice = "default"; break;
default: choice = "unknown"; break;
}
- send_message(user, nickserv, "NSMSG_SET_ANNOUNCEMENTS", choice);
+ reply("NSMSG_SET_ANNOUNCEMENTS", choice);
return 1;
}
static OPTION_FUNC(opt_password)
{
+ char crypted[MD5_CRYPT_LENGTH+1];
+ if(argc < 1) {
+ return 0;
+ }
if (!override) {
- send_message(user, nickserv, "NSMSG_USE_CMD_PASS");
+ reply("NSMSG_USE_CMD_PASS");
return 0;
}
- if (argc > 1)
- cryptpass(argv[1], hi->passwd);
+ cryptpass(argv[1], crypted);
+#ifdef WITH_LDAP
+ if(nickserv_conf.ldap_enable && nickserv_conf.ldap_admin_dn) {
+ int rc;
+ if((rc = ldap_do_modify(hi->handle, crypted, NULL)) != LDAP_SUCCESS) {
+ reply("NSMSG_LDAP_FAIL", ldap_err2string(rc));
+ return 0;
+ }
+ }
+#endif
+ strcpy(hi->passwd, crypted);
+ if (nickserv_conf.sync_log)
+ SyncLog("PASSCHANGE %s %s", hi->handle, hi->passwd);
- send_message(user, nickserv, "NSMSG_SET_PASSWORD", "***");
+ reply("NSMSG_SET_PASSWORD", "***");
return 1;
}
unsigned int ii, flen;
if (!override) {
- send_message(user, nickserv, "MSG_SETTING_PRIVILEGED", argv[0]);
+ reply("MSG_SETTING_PRIVILEGED", argv[0]);
return 0;
}
flags[flen++] = handle_flags[ii];
flags[flen] = '\0';
if (hi->flags)
- send_message(user, nickserv, "NSMSG_SET_FLAGS", flags);
+ reply("NSMSG_SET_FLAGS", flags);
else
- send_message(user, nickserv, "NSMSG_SET_FLAGS", user_find_message(user, "MSG_NONE"));
+ reply("NSMSG_SET_FLAGS", user_find_message(user, "MSG_NONE"));
return 1;
}
{
if (argc > 1) {
const char *str;
- if (!is_valid_email_addr(argv[1])) {
- send_message(user, nickserv, "NSMSG_BAD_EMAIL_ADDR");
+ if (!valid_email(argv[1])) {
+ reply("NSMSG_BAD_EMAIL_ADDR");
return 0;
}
if ((str = sendmail_prohibited_address(argv[1]))) {
- send_message(user, nickserv, "NSMSG_EMAIL_PROHIBITED", argv[1], str);
+ reply("NSMSG_EMAIL_PROHIBITED", argv[1], str);
return 0;
}
if (hi->email_addr && !irccasecmp(hi->email_addr, argv[1]))
- send_message(user, nickserv, "NSMSG_EMAIL_SAME");
+ reply("NSMSG_EMAIL_SAME");
else if (!override)
- nickserv_make_cookie(user, hi, EMAIL_CHANGE, argv[1]);
+ nickserv_make_cookie(user, hi, EMAIL_CHANGE, argv[1], 0);
else {
+#ifdef WITH_LDAP
+ if(nickserv_conf.ldap_enable && nickserv_conf.ldap_admin_dn) {
+ int rc;
+ if((rc = ldap_do_modify(hi->handle, NULL, argv[1])) != LDAP_SUCCESS) {
+ reply("NSMSG_LDAP_FAIL", ldap_err2string(rc));
+ return 0;
+ }
+ }
+#endif
nickserv_set_email_addr(hi, argv[1]);
if (hi->cookie)
nickserv_eat_cookie(hi->cookie);
- send_message(user, nickserv, "NSMSG_SET_EMAIL", visible_email_addr(user, hi));
+ reply("NSMSG_SET_EMAIL", visible_email_addr(user, hi));
}
} else
- send_message(user, nickserv, "NSMSG_SET_EMAIL", visible_email_addr(user, hi));
+ reply("NSMSG_SET_EMAIL", visible_email_addr(user, hi));
return 1;
}
if (argc > 1) {
maxlogins = strtoul(argv[1], NULL, 0);
if ((maxlogins > nickserv_conf.hard_maxlogins) && !override) {
- send_message(user, nickserv, "NSMSG_BAD_MAX_LOGINS", nickserv_conf.hard_maxlogins);
+ reply("NSMSG_BAD_MAX_LOGINS", nickserv_conf.hard_maxlogins);
return 0;
}
hi->maxlogins = maxlogins;
}
maxlogins = hi->maxlogins ? hi->maxlogins : nickserv_conf.default_maxlogins;
- send_message(user, nickserv, "NSMSG_SET_MAXLOGINS", maxlogins);
+ reply("NSMSG_SET_MAXLOGINS", maxlogins);
+ return 1;
+}
+
+static OPTION_FUNC(opt_advanced)
+{
+ if (argc > 1) {
+ if (enabled_string(argv[1]))
+ HANDLE_SET_FLAG(hi, ADVANCED);
+ else if (disabled_string(argv[1]))
+ HANDLE_CLEAR_FLAG(hi, ADVANCED);
+ else {
+ reply("MSG_INVALID_BINARY", argv[1]);
+ return 0;
+ }
+ }
+
+ reply("NSMSG_SET_ADVANCED", user_find_message(user, HANDLE_FLAGGED(hi, ADVANCED) ? "MSG_ON" : "MSG_OFF"));
return 1;
}
if (argc > 1) {
lang = language_find(argv[1]);
if (irccasecmp(lang->name, argv[1]))
- send_message(user, nickserv, "NSMSG_LANGUAGE_NOT_FOUND", argv[1], lang->name);
+ reply("NSMSG_LANGUAGE_NOT_FOUND", argv[1], lang->name);
hi->language = lang;
}
- send_message(user, nickserv, "NSMSG_SET_LANGUAGE", hi->language->name);
+ reply("NSMSG_SET_LANGUAGE", hi->language->name);
return 1;
}
+/* Called from opserv from cmd_access */
int
oper_try_set_access(struct userNode *user, struct userNode *bot, struct handle_info *target, unsigned int new_level) {
if (!oper_has_access(user, bot, nickserv_conf.modoper_level, 0))
send_message(user, bot, "MSG_STUPID_ACCESS_CHANGE");
return 0;
}
+#ifdef WITH_LDAP
+ if(nickserv_conf.ldap_enable && nickserv_conf.ldap_oper_group_dn && nickserv_conf.ldap_admin_dn) {
+ int rc;
+ if(new_level > 0)
+ rc = ldap_add2group(target->handle, nickserv_conf.ldap_oper_group_dn);
+ else
+ rc = ldap_delfromgroup(target->handle, nickserv_conf.ldap_oper_group_dn);
+ if(rc != LDAP_SUCCESS && rc != LDAP_TYPE_OR_VALUE_EXISTS && rc != LDAP_NO_SUCH_ATTRIBUTE) {
+ send_message(user, bot, "NSMSG_LDAP_FAIL", ldap_err2string(rc));
+ return 0;
+ }
+ }
+#endif
if (target->opserv_level == new_level)
return 0;
log_module(NS_LOG, LOG_INFO, "Account %s setting oper level for account %s to %d (from %d).",
int res;
if (!override) {
- send_message(user, nickserv, "MSG_SETTING_PRIVILEGED", argv[0]);
+ reply("MSG_SETTING_PRIVILEGED", argv[0]);
return 0;
}
res = (argc > 1) ? oper_try_set_access(user, nickserv, hi, strtoul(argv[1], NULL, 0)) : 0;
- send_message(user, nickserv, "NSMSG_SET_LEVEL", hi->opserv_level);
+ reply("NSMSG_SET_LEVEL", hi->opserv_level);
return res;
}
static OPTION_FUNC(opt_epithet)
{
- if (!override) {
- send_message(user, nickserv, "MSG_SETTING_PRIVILEGED", argv[0]);
- return 0;
- }
-
if ((argc > 1) && oper_has_access(user, nickserv, nickserv_conf.set_epithet_level, 0)) {
- char *epithet = unsplit_string(argv+1, argc-1, NULL);
+ char *epithet;
+ struct userNode *target, *next_un;
+
+ if (!override) {
+ reply("MSG_SETTING_PRIVILEGED", argv[0]);
+ return 0;
+ }
+
+ epithet = unsplit_string(argv+1, argc-1, NULL);
+
if (hi->epithet)
free(hi->epithet);
if ((epithet[0] == '*') && !epithet[1])
hi->epithet = NULL;
else
hi->epithet = strdup(epithet);
+
+ for (target = hi->users; target; target = next_un) {
+ irc_swhois(nickserv, target, hi->epithet);
+
+ next_un = target->next_authed;
+ }
}
if (hi->epithet)
- send_message(user, nickserv, "NSMSG_SET_EPITHET", hi->epithet);
+ reply("NSMSG_SET_EPITHET", hi->epithet);
else
- send_message(user, nickserv, "NSMSG_SET_EPITHET", user_find_message(user, "MSG_NONE"));
+ reply("NSMSG_SET_EPITHET", user_find_message(user, "MSG_NONE"));
return 1;
}
static OPTION_FUNC(opt_title)
{
- const char *title;
-
- if (!override) {
- send_message(user, nickserv, "MSG_SETTING_PRIVILEGED", argv[0]);
- return 0;
- }
+ char *title;
+ const char *none;
+ char *sptr;
if ((argc > 1) && oper_has_access(user, nickserv, nickserv_conf.set_title_level, 0)) {
- title = argv[1];
- if (strchr(title, '.')) {
- send_message(user, nickserv, "NSMSG_TITLE_INVALID");
+ if (!override) {
+ reply("MSG_SETTING_PRIVILEGED", argv[0]);
return 0;
}
- free(hi->fakehost);
- if (!strcmp(title, "*")) {
+
+ title = argv[1];
+ if(!strcmp(title, "*")) {
+ free(hi->fakehost);
hi->fakehost = NULL;
- } else {
+ }
+ else {
+ if (strchr(title, '.')) {
+ reply("NSMSG_TITLE_INVALID");
+ return 0;
+ }
+ /* Alphanumeric titles only. */
+ for(sptr = title; *sptr; sptr++) {
+ if(!isalnum(*sptr) && *sptr != '-') {
+ reply("NSMSG_TITLE_INVALID");
+ return 0;
+ }
+ }
+ if ((strlen(user->handle_info->handle) + strlen(title) +
+ strlen(nickserv_conf.titlehost_suffix) + 2) > HOSTLEN) {
+ reply("NSMSG_TITLE_TRUNCATED");
+ return 0;
+ }
+ free(hi->fakehost);
hi->fakehost = malloc(strlen(title)+2);
hi->fakehost[0] = '.';
strcpy(hi->fakehost+1, title);
apply_fakehost(hi);
} else if (hi->fakehost && (hi->fakehost[0] == '.'))
title = hi->fakehost + 1;
- else
- title = NULL;
+ else {
+ /* If theres no title set then the default title will therefore
+ be the first part of hidden_host in x3.conf, so for
+ consistency with opt_fakehost we will print this here.
+ This isnt actually used in P10, its just handled to keep from crashing... */
+ char *hs, *hidden_suffix, *rest;
+
+ hs = conf_get_data("server/hidden_host", RECDB_QSTRING);
+ hidden_suffix = strdup(hs);
+
+ /* Yes we do this twice */
+ if((rest = strchr(hidden_suffix, '.')))
+ {
+ *rest = '\0';
+ title = hidden_suffix;
+ }
+ else
+ {
+ /* A lame default if someone configured hidden_host to something lame */
+ title = strdup("users");
+ free(hidden_suffix);
+ }
+
+ }
+
if (!title)
- title = user_find_message(user, "MSG_NONE");
- send_message(user, nickserv, "NSMSG_SET_TITLE", title);
+ none = user_find_message(user, "MSG_NONE");
+ send_message(user, nickserv, "NSMSG_SET_TITLE", title ? title : none);
return 1;
}
-static OPTION_FUNC(opt_fakehost)
+int
+check_vhost(char *vhost, struct userNode *user, struct svccmd *cmd)
{
- const char *fake;
+ unsigned int y;
- if (!override) {
- send_message(user, nickserv, "MSG_SETTING_PRIVILEGED", argv[0]);
- return 0;
+ // check for a dot in the vhost
+ if(strchr(vhost, '.') == NULL) {
+ reply("NSMSG_NOT_VALID_FAKEHOST_DOT", vhost);
+ return 0;
+ }
+
+ // check for a @ in the vhost
+ if(strchr(vhost, '@') != NULL) {
+ reply("NSMSG_NOT_VALID_FAKEHOST_AT", vhost);
+ return 0;
}
+ // check for denied words, inspired by monk at paki.sex
+ for(y = 0; y < nickserv_conf.denied_fakehost_words->used; y++) {
+ if(strstr(vhost, nickserv_conf.denied_fakehost_words->list[y]) != NULL) {
+ reply("NSMSG_DENIED_FAKEHOST_WORD", vhost, nickserv_conf.denied_fakehost_words->list[y]);
+ return 0;
+ }
+ }
+
+ // check for ircu's HOSTLEN length.
+ if(strlen(vhost) >= HOSTLEN) {
+ reply("NSMSG_NOT_VALID_FAKEHOST_LEN", vhost);
+ return 0;
+ }
+
+ /* This can be handled by the regex now if desired.
+ if (vhost[strspn(vhost, "0123456789.")]) {
+ hostname = vhost + strlen(vhost);
+ for (depth = 1; depth && (hostname > vhost); depth--) {
+ hostname--;
+ while ((hostname > vhost) && (*hostname != '.')) hostname--;
+ }
+
+ if (*hostname == '.') hostname++; * advance past last dot we saw *
+ if(strlen(hostname) > 4) {
+ reply("NSMSG_NOT_VALID_FAKEHOST_TLD_LEN", vhost);
+ return 0;
+ }
+ }
+ */
+ /* test either regex or as valid handle */
+ if (nickserv_conf.valid_fakehost_regex_set) {
+ int err = regexec(&nickserv_conf.valid_fakehost_regex, vhost, 0, 0, 0);
+ if (err) {
+ char buff[256];
+ buff[regerror(err, &nickserv_conf.valid_fakehost_regex, buff, sizeof(buff))] = 0;
+ log_module(NS_LOG, LOG_INFO, "regexec error: %s (%d)", buff, err);
+ }
+ if(err == REG_NOMATCH) {
+ reply("NSMSG_NOT_VALID_FAKEHOST_REGEX", vhost);
+ return 0;
+ }
+ }
+
+
+ return 1;
+}
+
+static OPTION_FUNC(opt_fakehost)
+{
+ const char *fake;
+
if ((argc > 1) && oper_has_access(user, nickserv, nickserv_conf.set_fakehost_level, 0)) {
+ if (!override) {
+ reply("MSG_SETTING_PRIVILEGED", argv[0]);
+ return 0;
+ }
+
fake = argv[1];
if ((strlen(fake) > HOSTLEN) || (fake[0] == '.')) {
- send_message(user, nickserv, "NSMSG_FAKEHOST_INVALID");
+ reply("NSMSG_FAKEHOST_INVALID", HOSTLEN);
return 0;
}
- free(hi->fakehost);
- if (!strcmp(fake, "*"))
- hi->fakehost = NULL;
- else
+ if (!strcmp(fake, "*")) {
+ if(hi->fakehost) {
+ free(hi->fakehost);
+ hi->fakehost = NULL;
+ }
+ }
+ else if (!check_vhost(argv[1], user, cmd)) {
+ /* check_vhost takes care of error reply */
+ return 0;
+ }
+ else {
+ if(hi->fakehost)
+ free(hi->fakehost);
hi->fakehost = strdup(fake);
- fake = hi->fakehost;
+ }
apply_fakehost(hi);
+ fake = hi->fakehost;
} else
fake = generate_fakehost(hi);
+
+ /* Tell them we set the host */
if (!fake)
fake = user_find_message(user, "MSG_NONE");
- send_message(user, nickserv, "NSMSG_SET_FAKEHOST", fake);
+ reply("NSMSG_SET_FAKEHOST", fake);
+ return 1;
+}
+
+static OPTION_FUNC(opt_note)
+{
+ if (!override) {
+ reply("MSG_SETTING_PRIVILEGED", argv[0]);
+ return 0;
+ }
+
+ if (argc > 1) {
+ char *text = unsplit_string(argv + 1, argc - 1, NULL);
+
+ if (hi->note)
+ free(hi->note);
+
+ if ((text[0] == '*') && !text[1])
+ hi->note = NULL;
+ else {
+ if (!(hi->note = nickserv_add_note(user->handle_info->handle, now, text)))
+ hi->note = NULL;
+ }
+ }
+
+ reply("NSMSG_SET_NOTE", hi->note ? hi->note->note : user_find_message(user, "MSG_NONE"));
return 1;
}
passwd = argv[1];
argv[1] = "****";
if (checkpass(passwd, hi->passwd)) {
- nickserv_unregister_handle(hi, user);
- return 1;
+ if(nickserv_unregister_handle(hi, user, cmd->parent->bot))
+ return 1;
+ else
+ return 0;
} else {
log_module(NS_LOG, LOG_INFO, "Account '%s' tried to unregister with the wrong password.", hi->handle);
reply("NSMSG_PASSWORD_INVALID");
struct handle_info *hi;
NICKSERV_MIN_PARMS(2);
- if (!(hi = get_victim_oper(user, argv[1])))
+ if (!(hi = get_victim_oper(cmd, user, argv[1])))
+ return 0;
+ if(nickserv_unregister_handle(hi, user, cmd->parent->bot))
+ return 1;
+ else
return 0;
- nickserv_unregister_handle(hi, user);
- return 0;
}
static NICKSERV_FUNC(cmd_status)
for (it = dict_first(nickserv_handle_dict); it; it = iter_next(it)) {
hi = iter_data(it);
-#ifdef WITH_PROTOCOL_BAHAMUT
- assert(hi->id);
-#endif
saxdb_start_record(ctx, iter_key(it), 0);
if (hi->announcements != '?') {
flags[0] = hi->announcements;
saxdb_write_string(ctx, KEY_EMAIL_ADDR, hi->email_addr);
if (hi->epithet)
saxdb_write_string(ctx, KEY_EPITHET, hi->epithet);
+ if (hi->note) {
+ saxdb_start_record(ctx, KEY_NOTE_NOTE, 0);
+ saxdb_write_string(ctx, KEY_NOTE_SETTER, hi->note->setter);
+ saxdb_write_int(ctx, KEY_NOTE_DATE, hi->note->date);
+ saxdb_write_string(ctx, KEY_NOTE_NOTE, hi->note->note);
+ saxdb_end_record(ctx);
+ }
+
if (hi->fakehost)
saxdb_write_string(ctx, KEY_FAKEHOST, hi->fakehost);
if (hi->flags) {
flags[flen] = 0;
saxdb_write_string(ctx, KEY_FLAGS, flags);
}
-#ifdef WITH_PROTOCOL_BAHAMUT
- saxdb_write_int(ctx, KEY_ID, hi->id);
-#endif
if (hi->infoline)
saxdb_write_string(ctx, KEY_INFO, hi->infoline);
if (hi->last_quit_host[0])
saxdb_write_int(ctx, KEY_LAST_SEEN, hi->lastseen);
if (hi->masks->used)
saxdb_write_string_list(ctx, KEY_MASKS, hi->masks);
+ if (hi->ignores->used)
+ saxdb_write_string_list(ctx, KEY_IGNORES, hi->ignores);
if (hi->maxlogins)
saxdb_write_int(ctx, KEY_MAXLOGINS, hi->maxlogins);
if (hi->nicks) {
saxdb_write_string(ctx, KEY_USERLIST_STYLE, flags);
saxdb_end_record(ctx);
}
+
return 0;
}
struct userNode *last_user;
struct userData *cList, *cListNext;
unsigned int ii, jj, n;
- char buffer[MAXLEN];
NICKSERV_MIN_PARMS(3);
- if (!(hi_from = get_victim_oper(user, argv[1])))
+ if (!(hi_from = get_victim_oper(cmd, user, argv[1])))
return 0;
- if (!(hi_to = get_victim_oper(user, argv[2])))
+ if (!(hi_to = get_victim_oper(cmd, user, argv[2])))
return 0;
if (hi_to == hi_from) {
reply("NSMSG_CANNOT_MERGE_SELF", hi_to->handle);
string_list_append(hi_to->masks, strdup(mask));
}
+ /* Merge the ignores. */
+ for (ii=0; ii<hi_from->ignores->used; ii++) {
+ char *ignore = hi_from->ignores->list[ii];
+ for (jj=0; jj<hi_to->ignores->used; jj++)
+ if (match_ircglobs(hi_to->ignores->list[jj], ignore))
+ break;
+ if (jj==hi_to->ignores->used) /* Nothing from the "to" handle covered this mask, so add it. */
+ string_list_append(hi_to->ignores, strdup(ignore));
+ }
+
/* Merge the lists of authed users. */
if (hi_to->users) {
for (last_user=hi_to->users; last_user->next_authed; last_user=last_user->next_authed) ;
if (hi_from->lastseen > hi_to->lastseen)
hi_to->lastseen = hi_from->lastseen;
+ /* Does a fakehost carry over? (This intentionally doesn't set it
+ * for users previously attached to hi_to. They'll just have to
+ * reconnect.)
+ */
+ if (hi_from->fakehost && !hi_to->fakehost)
+ hi_to->fakehost = strdup(hi_from->fakehost);
+
/* Notify of success. */
- sprintf(buffer, "%s (%s) merged account %s into %s.", user->nick, user->handle_info->handle, hi_from->handle, hi_to->handle);
reply("NSMSG_HANDLES_MERGED", hi_from->handle, hi_to->handle);
- global_message(MESSAGE_RECIPIENT_STAFF, buffer);
+ global_message_args(MESSAGE_RECIPIENT_OPERS, "NSMSG_ACCOUNT_MERGED", user->nick,
+ user->handle_info->handle, hi_from->handle, hi_to->handle);
/* Unregister the "from" handle. */
- nickserv_unregister_handle(hi_from, NULL);
+ nickserv_unregister_handle(hi_from, NULL, cmd->parent->bot);
+ /* TODO: fix it so that if the ldap delete in nickserv_unregister_handle fails,
+ * the process isn't completed.
+ */
return 1;
}
const char *hostmask;
const char *handlemask;
const char *emailmask;
+#ifdef WITH_LDAP
+ unsigned int inldap;
+#endif
};
typedef void (*discrim_search_func)(struct userNode *source, struct handle_info *hi);
};
static struct nickserv_discrim *
-nickserv_discrim_create(struct userNode *user, unsigned int argc, char *argv[])
+nickserv_discrim_create(struct svccmd *cmd, struct userNode *user, unsigned int argc, char *argv[])
{
unsigned int i;
struct nickserv_discrim *discrim;
discrim->min_registered = 0;
discrim->max_registered = INT_MAX;
discrim->lastseen = now;
+#ifdef WITH_LDAP
+ discrim->inldap = 2;
+#endif
for (i=0; i<argc; i++) {
if (i == argc - 1) {
- send_message(user, nickserv, "MSG_MISSING_PARAMS", argv[i]);
+ reply("MSG_MISSING_PARAMS", argv[i]);
goto fail;
}
if (!irccasecmp(argv[i], "limit")) {
discrim->max_registered = now - ParseInterval(cmp+1) - 1;
}
} else {
- send_message(user, nickserv, "MSG_INVALID_CRITERIA", cmp);
+ reply("MSG_INVALID_CRITERIA", cmp);
}
} else if (!irccasecmp(argv[i], "seen")) {
discrim->lastseen = now - ParseInterval(argv[++i]);
i++;
if (!irccasecmp(argv[i], "exact")) {
if (i == argc - 1) {
- send_message(user, nickserv, "MSG_MISSING_PARAMS", argv[i]);
+ reply("MSG_MISSING_PARAMS", argv[i]);
goto fail;
}
discrim->hostmask_type = EXACT;
} else if (!irccasecmp(argv[i], "subset")) {
if (i == argc - 1) {
- send_message(user, nickserv, "MSG_MISSING_PARAMS", argv[i]);
+ reply("MSG_MISSING_PARAMS", argv[i]);
goto fail;
}
discrim->hostmask_type = SUBSET;
} else if (!irccasecmp(argv[i], "superset")) {
if (i == argc - 1) {
- send_message(user, nickserv, "MSG_MISSING_PARAMS", argv[i]);
+ reply("MSG_MISSING_PARAMS", argv[i]);
goto fail;
}
discrim->hostmask_type = SUPERSET;
} else if (!irccasecmp(argv[i], "lastquit") || !irccasecmp(argv[i], "lastauth")) {
if (i == argc - 1) {
- send_message(user, nickserv, "MSG_MISSING_PARAMS", argv[i]);
+ reply("MSG_MISSING_PARAMS", argv[i]);
goto fail;
}
discrim->hostmask_type = LASTQUIT;
discrim->hostmask_type = SUPERSET;
}
discrim->hostmask = argv[++i];
- } else if (!irccasecmp(argv[i], "handlemask") || !irccasecmp(argv[i], "accountmask")) {
+ } else if (!irccasecmp(argv[i], "handlemask") || !irccasecmp(argv[i], "accountmask") || !irccasecmp(argv[i], "account")) {
if (!irccasecmp(argv[++i], "*")) {
discrim->handlemask = 0;
} else {
}
} else if (!irccasecmp(argv[i], "email")) {
if (user->handle_info->opserv_level < nickserv_conf.email_search_level) {
- send_message(user, nickserv, "MSG_NO_SEARCH_ACCESS", "email");
+ reply("MSG_NO_SEARCH_ACCESS", "email");
goto fail;
} else if (!irccasecmp(argv[++i], "*")) {
discrim->emailmask = 0;
discrim->min_level = strtoul(cmp+1, NULL, 0) + 1;
}
} else {
- send_message(user, nickserv, "MSG_INVALID_CRITERIA", cmp);
+ reply("MSG_INVALID_CRITERIA", cmp);
}
- } else {
- send_message(user, nickserv, "MSG_INVALID_CRITERIA", argv[i]);
+#ifdef WITH_LDAP
+ } else if (nickserv_conf.ldap_enable && !irccasecmp(argv[i], "inldap")) {
+ i++;
+ if(true_string(argv[i])) {
+ discrim->inldap = 1;
+ }
+ else if (false_string(argv[i])) {
+ discrim->inldap = 0;
+ }
+ else {
+ reply("MSG_INVALID_BINARY", argv[i]);
+ }
+#endif
+ } else {
+ reply("MSG_INVALID_CRITERIA", argv[i]);
goto fail;
}
}
}
if (!nick) return 0;
}
+#ifdef WITH_LDAP
+ if(nickserv_conf.ldap_enable && discrim->inldap != 2) {
+ int rc;
+ rc = ldap_get_user_info(hi->handle, NULL);
+ if(discrim->inldap == 1 && rc != LDAP_SUCCESS)
+ return 0;
+ if(discrim->inldap == 0 && rc == LDAP_SUCCESS)
+ return 0;
+ }
+
+#endif
return 1;
}
search_unregister_func (struct userNode *source, struct handle_info *match)
{
if (oper_has_access(source, nickserv, match->opserv_level, 0))
- nickserv_unregister_handle(match, source);
+ nickserv_unregister_handle(match, source, nickserv); // XXX nickserv hard coded
+}
+
+static void
+search_add2ldap_func (struct userNode *source, struct handle_info *match)
+{
+#ifdef WITH_LDAP
+ int rc;
+ if(match->email_addr && match->passwd && match->handle) {
+ rc = ldap_do_add(match->handle, match->passwd, match->email_addr);
+ if(rc != LDAP_SUCCESS) {
+ send_message(source, nickserv, "NSMSG_LDAP_FAIL_ADD", match->handle, ldap_err2string(rc));
+ }
+ }
+#endif
}
static int
qsort(hil.list, hil.used, sizeof(hil.list[0]), nickserv_sort_accounts_by_access);
tbl.length = hil.used + 1;
tbl.width = 2;
- tbl.flags = TABLE_NO_FREE;
+ tbl.flags = TABLE_NO_FREE | TABLE_REPEAT_ROWS | TABLE_REPEAT_HEADERS;
tbl.contents = malloc(tbl.length * sizeof(tbl.contents[0]));
tbl.contents[0] = ary = malloc(tbl.width * sizeof(ary[0]));
ary[0] = "Account";
tbl.contents[++ii] = ary;
}
table_send(cmd->parent->bot, user->nick, 0, NULL, tbl);
- reply("MSG_MATCH_COUNT", hil.used);
+ /*reply("MSG_MATCH_COUNT", hil.used); */
for (ii = 0; ii < hil.used; ii++)
free(tbl.contents[ii]);
free(tbl.contents);
action = search_count_func;
else if (!irccasecmp(argv[1], "unregister"))
action = search_unregister_func;
+#ifdef WITH_LDAP
+ else if (nickserv_conf.ldap_enable && !irccasecmp(argv[1], "add2ldap"))
+ action = search_add2ldap_func;
+#endif
else {
reply("NSMSG_INVALID_ACTION", argv[1]);
return 0;
if (subcmd && !svccmd_can_invoke(user, nickserv, subcmd, NULL, SVCCMD_NOISY))
return 0;
- discrim = nickserv_discrim_create(user, argc-2, argv+2);
+ discrim = nickserv_discrim_create(cmd, user, argc-2, argv+2);
if (!discrim)
return 0;
}
static void
-nickserv_db_read_handle(const char *handle, dict_t obj)
+nickserv_db_read_handle(char *handle, dict_t obj)
{
const char *str;
- struct string_list *masks, *slist;
+ struct string_list *masks, *slist, *ignores;
struct handle_info *hi;
struct userNode *authed_users;
+ struct userData *channels;
unsigned long int id;
unsigned int ii;
dict_t subdb;
+ char *setter, *note;
+ time_t date;
str = database_get_data(obj, KEY_ID, RECDB_QSTRING);
id = str ? strtoul(str, NULL, 0) : 0;
}
if ((hi = get_handle_info(handle))) {
authed_users = hi->users;
+ channels = hi->channels;
hi->users = NULL;
+ hi->channels = NULL;
dict_remove(nickserv_handle_dict, hi->handle);
} else {
authed_users = NULL;
+ channels = NULL;
}
+ if(nickserv_conf.force_handles_lowercase)
+ irc_strtolower(handle);
hi = register_handle(handle, str, id);
if (authed_users) {
hi->users = authed_users;
authed_users = authed_users->next_authed;
}
}
+ hi->channels = channels;
masks = database_get_data(obj, KEY_MASKS, RECDB_STRING_LIST);
hi->masks = masks ? string_list_copy(masks) : alloc_string_list(1);
+ ignores = database_get_data(obj, KEY_IGNORES, RECDB_STRING_LIST);
+ hi->ignores = ignores ? string_list_copy(ignores) : alloc_string_list(1);
str = database_get_data(obj, KEY_MAXLOGINS, RECDB_QSTRING);
hi->maxlogins = str ? strtoul(str, NULL, 0) : 0;
str = database_get_data(obj, KEY_LANGUAGE, RECDB_QSTRING);
hi->flags |= 1 << (handle_inverse_flags[(unsigned char)str[ii]] - 1);
}
str = database_get_data(obj, KEY_USERLIST_STYLE, RECDB_QSTRING);
- hi->userlist_style = str ? str[0] : HI_STYLE_ZOOT;
+ hi->userlist_style = str ? str[0] : HI_DEFAULT_STYLE;
str = database_get_data(obj, KEY_ANNOUNCEMENTS, RECDB_QSTRING);
hi->announcements = str ? str[0] : '?';
str = database_get_data(obj, KEY_SCREEN_WIDTH, RECDB_QSTRING);
str = database_get_data(obj, KEY_EPITHET, RECDB_QSTRING);
if (str)
hi->epithet = strdup(str);
+ subdb = database_get_data(obj, KEY_NOTE_NOTE, RECDB_OBJECT);
+ if (subdb) {
+ setter = database_get_data(subdb, KEY_NOTE_SETTER, RECDB_QSTRING);
+ str = database_get_data(subdb, KEY_NOTE_DATE, RECDB_QSTRING);
+ date = str ? (time_t)strtoul(str, NULL, 0) : now;
+ note = database_get_data(subdb, KEY_NOTE_NOTE, RECDB_QSTRING);
+ if (setter && date && note)
+ {
+ if (!(hi->note = nickserv_add_note(setter, date, note)))
+ hi->note = NULL;
+ }
+ }
+
str = database_get_data(obj, KEY_FAKEHOST, RECDB_QSTRING);
if (str)
hi->fakehost = strdup(str);
+
subdb = database_get_data(obj, KEY_COOKIE, RECDB_OBJECT);
if (subdb) {
const char *data, *type, *expires, *cookie_str;
nickserv_saxdb_read(dict_t db) {
dict_iterator_t it;
struct record_data *rd;
+ char *handle;
for (it=dict_first(db); it; it=iter_next(it)) {
rd = iter_data(it);
- nickserv_db_read_handle(iter_key(it), rd->d.object);
+ handle = strdup(iter_key(it));
+ nickserv_db_read_handle(handle, rd->d.object);
+ free(handle);
}
return 0;
}
expiry = hi->channels ? nickserv_conf.handle_expire_delay : nickserv_conf.nochan_handle_expire_delay;
if ((now - hi->lastseen) > expiry) {
log_module(NS_LOG, LOG_INFO, "Expiring account %s for inactivity.", hi->handle);
- nickserv_unregister_handle(hi, NULL);
+ nickserv_unregister_handle(hi, NULL, NULL);
}
}
dict_t conf_node, child;
const char *str;
dict_iterator_t it;
+ struct string_list *strlist;
if (!(conf_node = conf_get_data(NICKSERV_CONF_NAME, RECDB_OBJECT))) {
log_module(NS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", NICKSERV_CONF_NAME);
} else {
nickserv_conf.valid_nick_regex_set = 0;
}
+ str = database_get_data(conf_node, KEY_VALID_FAKEHOST_REGEX, RECDB_QSTRING);
+ if (nickserv_conf.valid_fakehost_regex_set)
+ regfree(&nickserv_conf.valid_fakehost_regex);
+ if (str) {
+ int err = regcomp(&nickserv_conf.valid_fakehost_regex, str, REG_EXTENDED|REG_ICASE|REG_NOSUB);
+ nickserv_conf.valid_fakehost_regex_set = !err;
+ if (err) log_module(NS_LOG, LOG_ERROR, "Bad valid_fakehost_regex (error %d)", err);
+ } else {
+ nickserv_conf.valid_fakehost_regex_set = 0;
+ }
str = database_get_data(conf_node, KEY_NICKS_PER_HANDLE, RECDB_QSTRING);
if (!str)
str = database_get_data(conf_node, KEY_NICKS_PER_ACCOUNT, RECDB_QSTRING);
nickserv_conf.email_visible_level = str ? strtoul(str, NULL, 0) : 800;
str = database_get_data(conf_node, KEY_EMAIL_ENABLED, RECDB_QSTRING);
nickserv_conf.email_enabled = str ? enabled_string(str) : 0;
+ str = database_get_data(conf_node, KEY_SYNC_LOG, RECDB_QSTRING);
+ nickserv_conf.sync_log = str ? enabled_string(str) : 0;
str = database_get_data(conf_node, KEY_COOKIE_TIMEOUT, RECDB_QSTRING);
nickserv_conf.cookie_timeout = str ? ParseInterval(str) : 24*3600;
str = database_get_data(conf_node, KEY_EMAIL_REQUIRED, RECDB_QSTRING);
nickserv_conf.email_search_level = str ? strtoul(str, NULL, 0) : 600;
str = database_get_data(conf_node, KEY_TITLEHOST_SUFFIX, RECDB_QSTRING);
nickserv_conf.titlehost_suffix = str ? str : "example.net";
+
+ free_string_list(nickserv_conf.denied_fakehost_words);
+ strlist = database_get_data(conf_node, KEY_DENIED_FAKEHOST_WORDS, RECDB_STRING_LIST);
+ if(strlist)
+ strlist = string_list_copy(strlist);
+ else {
+ strlist = alloc_string_list(4);
+ string_list_append(strlist, strdup("sex"));
+ string_list_append(strlist, strdup("fuck"));
+ }
+ nickserv_conf.denied_fakehost_words = strlist;
+
+ str = database_get_data(conf_node, KEY_DEFAULT_STYLE, RECDB_QSTRING);
+ nickserv_conf.default_style = str ? str[0] : HI_DEFAULT_STYLE;
+
+ str = database_get_data(conf_node, KEY_AUTO_OPER, RECDB_QSTRING);
+ nickserv_conf.auto_oper = str ? str : "";
+
+ str = database_get_data(conf_node, KEY_AUTO_ADMIN, RECDB_QSTRING);
+ nickserv_conf.auto_admin = str ? str : "";
+
str = conf_get_data("server/network", RECDB_QSTRING);
nickserv_conf.network_name = str ? str : "some IRC network";
if (!nickserv_conf.auth_policer_params) {
child = database_get_data(conf_node, KEY_AUTH_POLICER, RECDB_OBJECT);
for (it=dict_first(child); it; it=iter_next(it))
set_policer_param(iter_key(it), iter_data(it), nickserv_conf.auth_policer_params);
+
+ str = database_get_data(conf_node, KEY_LDAP_ENABLE, RECDB_QSTRING);
+ nickserv_conf.ldap_enable = str ? strtoul(str, NULL, 0) : 0;
+
+ str = database_get_data(conf_node, KEY_FORCE_HANDLES_LOWERCASE, RECDB_QSTRING);
+ nickserv_conf.force_handles_lowercase = str ? strtol(str, NULL, 0) : 0;
+
+#ifndef WITH_LDAP
+ if(nickserv_conf.ldap_enable > 0) {
+ /* ldap is enabled but not compiled in - error out */
+ log_module(MAIN_LOG, LOG_ERROR, "ldap is enabled in config, but not compiled in!");
+ nickserv_conf.ldap_enable = 0;
+ sleep(5);
+ }
+#endif
+
+#ifdef WITH_LDAP
+ str = database_get_data(conf_node, KEY_LDAP_URI, RECDB_QSTRING);
+ nickserv_conf.ldap_uri = str ? str : "";
+
+ str = database_get_data(conf_node, KEY_LDAP_BASE, RECDB_QSTRING);
+ nickserv_conf.ldap_base = str ? str : "";
+
+ str = database_get_data(conf_node, KEY_LDAP_DN_FMT, RECDB_QSTRING);
+ nickserv_conf.ldap_dn_fmt = str ? str : "";
+
+ str = database_get_data(conf_node, KEY_LDAP_VERSION, RECDB_QSTRING);
+ nickserv_conf.ldap_version = str ? strtoul(str, NULL, 0) : 3;
+
+ str = database_get_data(conf_node, KEY_LDAP_AUTOCREATE, RECDB_QSTRING);
+ nickserv_conf.ldap_autocreate = str ? strtoul(str, NULL, 0) : 0;
+
+ str = database_get_data(conf_node, KEY_LDAP_TIMEOUT, RECDB_QSTRING);
+ nickserv_conf.ldap_timeout = str ? strtoul(str, NULL, 0) : 5;
+
+ str = database_get_data(conf_node, KEY_LDAP_ADMIN_DN, RECDB_QSTRING);
+ nickserv_conf.ldap_admin_dn = str ? str : "";
+
+ str = database_get_data(conf_node, KEY_LDAP_ADMIN_PASS, RECDB_QSTRING);
+ nickserv_conf.ldap_admin_pass = str ? str : "";
+
+ str = database_get_data(conf_node, KEY_LDAP_FIELD_ACCOUNT, RECDB_QSTRING);
+ nickserv_conf.ldap_field_account = str ? str : "";
+
+ str = database_get_data(conf_node, KEY_LDAP_FIELD_PASSWORD, RECDB_QSTRING);
+ nickserv_conf.ldap_field_password = str ? str : "";
+
+ str = database_get_data(conf_node, KEY_LDAP_FIELD_EMAIL, RECDB_QSTRING);
+ nickserv_conf.ldap_field_email = str ? str : "";
+
+ str = database_get_data(conf_node, KEY_LDAP_OPER_GROUP_DN, RECDB_QSTRING);
+ nickserv_conf.ldap_oper_group_dn = str ? str : "";
+
+ str = database_get_data(conf_node, KEY_LDAP_FIELD_GROUP_MEMBER, RECDB_QSTRING);
+ nickserv_conf.ldap_field_group_member = str ? str : "";
+
+ free_string_list(nickserv_conf.ldap_object_classes);
+ strlist = database_get_data(conf_node, KEY_LDAP_OBJECT_CLASSES, RECDB_STRING_LIST);
+ if(strlist)
+ strlist = string_list_copy(strlist);
+ else {
+ strlist = alloc_string_list(4);
+ string_list_append(strlist, strdup("top"));
+ }
+ nickserv_conf.ldap_object_classes = strlist;
+
+#endif
+
}
static void
handle_account(struct userNode *user, const char *stamp)
{
struct handle_info *hi;
+ char *colon;
#ifdef WITH_PROTOCOL_P10
+ time_t timestamp = 0;
+
+ colon = strchr(stamp, ':');
+ if(colon && colon[1])
+ {
+ *colon = 0;
+ timestamp = atoi(colon+1);
+ }
hi = dict_find(nickserv_handle_dict, stamp, NULL);
+ if(hi && timestamp && hi->registered != timestamp)
+ {
+ log_module(MAIN_LOG, LOG_WARNING, "%s using account %s but timestamp does not match %lu is not %lu.", user->nick, stamp, timestamp, hi->registered);
+ return;
+ }
#else
hi = dict_find(nickserv_id_dict, stamp, NULL);
+ log_module(MAIN_LOG, LOG_WARNING, "Using non-P10 code in accounts, not tested at all!");
#endif
if (hi) {
void
init_nickserv(const char *nick)
{
+ struct chanNode *chan;
unsigned int i;
NS_LOG = log_register_type("NickServ", "file:nickserv.log");
reg_new_user_func(handle_new_user);
conf_register_reload(nickserv_conf_read);
nickserv_opt_dict = dict_new();
nickserv_email_dict = dict_new();
+
dict_set_free_keys(nickserv_email_dict, free);
dict_set_free_data(nickserv_email_dict, nickserv_free_email_addr);
nickserv_module = module_register("NickServ", NS_LOG, "nickserv.help", NULL);
- modcmd_register(nickserv_module, "AUTH", cmd_auth, 2, MODCMD_KEEP_BOUND, "flags", "+qualified,+loghostmask", NULL);
+/* Removed qualified_host as default requirement for AUTH, REGISTER, PASS, etc. nets
+ * can enable it per command using modcmd. (its a shitty default IMO, and now in 1.3
+ * a big pain to disable since its nolonger in the config file. ) -Rubin
+ */
+ modcmd_register(nickserv_module, "AUTH", cmd_auth, 2, MODCMD_KEEP_BOUND, "flags", "+loghostmask", NULL);
nickserv_define_func("ALLOWAUTH", cmd_allowauth, 0, 1, 0);
- nickserv_define_func("REGISTER", cmd_register, -1, 0, 1);
+ nickserv_define_func("REGISTER", cmd_register, -1, 0, 0);
nickserv_define_func("OREGISTER", cmd_oregister, 0, 1, 0);
- nickserv_define_func("UNREGISTER", cmd_unregister, -1, 1, 1);
+ nickserv_define_func("UNREGISTER", cmd_unregister, -1, 1, 0);
nickserv_define_func("OUNREGISTER", cmd_ounregister, 0, 1, 0);
nickserv_define_func("ADDMASK", cmd_addmask, -1, 1, 0);
nickserv_define_func("OADDMASK", cmd_oaddmask, 0, 1, 0);
nickserv_define_func("DELMASK", cmd_delmask, -1, 1, 0);
nickserv_define_func("ODELMASK", cmd_odelmask, 0, 1, 0);
- nickserv_define_func("PASS", cmd_pass, -1, 1, 1);
+ nickserv_define_func("PASS", cmd_pass, -1, 1, 0);
nickserv_define_func("SET", cmd_set, -1, 1, 0);
nickserv_define_func("OSET", cmd_oset, 0, 1, 0);
nickserv_define_func("ACCOUNTINFO", cmd_handleinfo, -1, 0, 0);
}
if (nickserv_conf.email_enabled) {
nickserv_define_func("AUTHCOOKIE", cmd_authcookie, -1, 0, 0);
- nickserv_define_func("RESETPASS", cmd_resetpass, -1, 0, 1);
- nickserv_define_func("COOKIE", cmd_cookie, -1, 0, 1);
+ nickserv_define_func("RESETPASS", cmd_resetpass, -1, 0, 0);
+ nickserv_define_func("COOKIE", cmd_cookie, -1, 0, 0);
nickserv_define_func("DELCOOKIE", cmd_delcookie, -1, 1, 0);
+ nickserv_define_func("ODELCOOKIE", cmd_odelcookie, 0, 1, 0);
dict_insert(nickserv_opt_dict, "EMAIL", opt_email);
}
nickserv_define_func("GHOST", cmd_ghost, -1, 1, 0);
+ /* ignore commands */
+ nickserv_define_func("ADDIGNORE", cmd_addignore, -1, 1, 0);
+ nickserv_define_func("OADDIGNORE", cmd_oaddignore, 0, 1, 0);
+ nickserv_define_func("DELIGNORE", cmd_delignore, -1, 1, 0);
+ nickserv_define_func("ODELIGNORE", cmd_odelignore, 0, 1, 0);
/* miscellaneous commands */
nickserv_define_func("STATUS", cmd_status, -1, 0, 0);
nickserv_define_func("SEARCH", cmd_search, 100, 1, 0);
dict_insert(nickserv_opt_dict, "TABLEWIDTH", opt_tablewidth);
dict_insert(nickserv_opt_dict, "COLOR", opt_color);
dict_insert(nickserv_opt_dict, "PRIVMSG", opt_privmsg);
- dict_insert(nickserv_opt_dict, "STYLE", opt_style);
+ dict_insert(nickserv_opt_dict, "AUTOHIDE", opt_autohide);
+ dict_insert(nickserv_opt_dict, "STYLE", opt_style);
dict_insert(nickserv_opt_dict, "PASS", opt_password);
dict_insert(nickserv_opt_dict, "PASSWORD", opt_password);
dict_insert(nickserv_opt_dict, "FLAGS", opt_flags);
dict_insert(nickserv_opt_dict, "ACCESS", opt_level);
dict_insert(nickserv_opt_dict, "LEVEL", opt_level);
dict_insert(nickserv_opt_dict, "EPITHET", opt_epithet);
+ dict_insert(nickserv_opt_dict, "NOTE", opt_note);
if (nickserv_conf.titlehost_suffix) {
dict_insert(nickserv_opt_dict, "TITLE", opt_title);
dict_insert(nickserv_opt_dict, "FAKEHOST", opt_fakehost);
}
dict_insert(nickserv_opt_dict, "ANNOUNCEMENTS", opt_announcements);
dict_insert(nickserv_opt_dict, "MAXLOGINS", opt_maxlogins);
+ dict_insert(nickserv_opt_dict, "ADVANCED", opt_advanced);
dict_insert(nickserv_opt_dict, "LANGUAGE", opt_language);
nickserv_handle_dict = dict_new();
dict_set_free_keys(nickserv_id_dict, free);
nickserv_nick_dict = dict_new();
- dict_set_free_data(nickserv_nick_dict, free_nick_info);
+ dict_set_free_data(nickserv_nick_dict, free);
nickserv_allow_auth_dict = dict_new();
userList_init(&curr_helpers);
if (nick) {
- nickserv = AddService(nick, "Nick Services", NULL);
+ const char *modes = conf_get_data("services/nickserv/modes", RECDB_QSTRING);
+ nickserv = AddService(nick, modes ? modes : NULL, "Nick Services", NULL);
nickserv_service = service_register(nickserv);
}
saxdb_register("NickServ", nickserv_saxdb_read, nickserv_saxdb_write);
reg_exit_func(nickserv_db_cleanup);
if(nickserv_conf.handle_expire_frequency)
timeq_add(now + nickserv_conf.handle_expire_frequency, expire_handles, NULL);
+
+ if(autojoin_channels && nickserv) {
+ for (i = 0; i < autojoin_channels->used; i++) {
+ chan = AddChannel(autojoin_channels->list[i], now, "+nt", NULL, NULL);
+ AddChannelUser(nickserv, chan)->modes |= MODE_CHANOP;
+ }
+ }
+#ifdef WITH_LDAP
+ ldap_do_init(nickserv_conf);
+#endif
+
message_register_table(msgtab);
}