1 /* nickserv.c - Nick/authentication service
2 * Copyright 2000-2004 srvx Development Team
4 * This file is part of x3.
6 * x3 is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with srvx; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 #include "opserv.h" /* for gag_create(), opserv_bad_channel() */
32 #include <tre/regex.h>
38 #define NICKSERV_CONF_NAME "services/nickserv"
40 #define KEY_DISABLE_NICKS "disable_nicks"
41 #define KEY_DEFAULT_HOSTMASK "default_hostmask"
42 #define KEY_NICKS_PER_HANDLE "nicks_per_handle"
43 #define KEY_NICKS_PER_ACCOUNT "nicks_per_account"
44 #define KEY_PASSWORD_MIN_LENGTH "password_min_length"
45 #define KEY_PASSWORD_MIN_DIGITS "password_min_digits"
46 #define KEY_PASSWORD_MIN_UPPER "password_min_upper"
47 #define KEY_PASSWORD_MIN_LOWER "password_min_lower"
48 #define KEY_VALID_HANDLE_REGEX "valid_handle_regex"
49 #define KEY_VALID_ACCOUNT_REGEX "valid_account_regex"
50 #define KEY_VALID_NICK_REGEX "valid_nick_regex"
51 #define KEY_VALID_FAKEHOST_REGEX "valid_fakehost_regex"
52 #define KEY_DB_BACKUP_FREQ "db_backup_freq"
53 #define KEY_MODOPER_LEVEL "modoper_level"
54 #define KEY_SET_EPITHET_LEVEL "set_epithet_level"
55 #define KEY_SET_TITLE_LEVEL "set_title_level"
56 #define KEY_SET_FAKEHOST_LEVEL "set_fakehost_level"
57 #define KEY_DENIED_FAKEHOST_WORDS "denied_fakehost_words"
58 #define KEY_TITLEHOST_SUFFIX "titlehost_suffix"
59 #define KEY_AUTO_OPER "auto_oper"
60 #define KEY_AUTO_ADMIN "auto_admin"
61 #define KEY_AUTO_OPER_PRIVS "auto_oper_privs"
62 #define KEY_AUTO_ADMIN_PRIVS "auto_admin_privs"
63 #define KEY_FLAG_LEVELS "flag_levels"
64 #define KEY_HANDLE_EXPIRE_FREQ "handle_expire_freq"
65 #define KEY_ACCOUNT_EXPIRE_FREQ "account_expire_freq"
66 #define KEY_HANDLE_EXPIRE_DELAY "handle_expire_delay"
67 #define KEY_ACCOUNT_EXPIRE_DELAY "account_expire_delay"
68 #define KEY_NOCHAN_HANDLE_EXPIRE_DELAY "nochan_handle_expire_delay"
69 #define KEY_NOCHAN_ACCOUNT_EXPIRE_DELAY "nochan_account_expire_delay"
70 #define KEY_DICT_FILE "dict_file"
71 #define KEY_NICK "nick"
72 #define KEY_LANGUAGE "language"
73 #define KEY_AUTOGAG_ENABLED "autogag_enabled"
74 #define KEY_AUTOGAG_DURATION "autogag_duration"
75 #define KEY_AUTH_POLICER "auth_policer"
76 #define KEY_EMAIL_VISIBLE_LEVEL "email_visible_level"
77 #define KEY_EMAIL_ENABLED "email_enabled"
78 #define KEY_EMAIL_REQUIRED "email_required"
79 #define KEY_SYNC_LOG "sync_log"
80 #define KEY_COOKIE_TIMEOUT "cookie_timeout"
81 #define KEY_ACCOUNTS_PER_EMAIL "accounts_per_email"
82 #define KEY_EMAIL_SEARCH_LEVEL "email_search_level"
83 #define KEY_DEFAULT_STYLE "default_style"
84 #define KEY_OUNREGISTER_INACTIVE "ounregister_inactive"
85 #define KEY_OUNREGISTER_FLAGS "ounregister_flags"
88 #define KEY_PASSWD "passwd"
89 #define KEY_NICKS "nicks"
90 #define KEY_MASKS "masks"
91 #define KEY_SSLFPS "sslfps"
92 #define KEY_IGNORES "ignores"
93 #define KEY_OPSERV_LEVEL "opserv_level"
94 #define KEY_FLAGS "flags"
95 #define KEY_REGISTER_ON "register"
96 #define KEY_LAST_SEEN "lastseen"
97 #define KEY_INFO "info"
98 #define KEY_USERLIST_STYLE "user_style"
99 #define KEY_SCREEN_WIDTH "screen_width"
100 #define KEY_LAST_AUTHED_HOST "last_authed_host"
101 #define KEY_LAST_QUIT_HOST "last_quit_host"
102 #define KEY_EMAIL_ADDR "email_addr"
103 #define KEY_COOKIE "cookie"
104 #define KEY_COOKIE_DATA "data"
105 #define KEY_COOKIE_TYPE "type"
106 #define KEY_COOKIE_EXPIRES "expires"
107 #define KEY_ACTIVATION "activation"
108 #define KEY_PASSWORD_CHANGE "password change"
109 #define KEY_EMAIL_CHANGE "email change"
110 #define KEY_ALLOWAUTH "allowauth"
111 #define KEY_EPITHET "epithet"
112 #define KEY_TABLE_WIDTH "table_width"
113 #define KEY_ANNOUNCEMENTS "announcements"
114 #define KEY_MAXLOGINS "maxlogins"
115 #define KEY_FAKEHOST "fakehost"
116 #define KEY_NOTE_NOTE "note"
117 #define KEY_NOTE_SETTER "setter"
118 #define KEY_NOTE_DATE "date"
119 #define KEY_KARMA "karma"
120 #define KEY_FORCE_HANDLES_LOWERCASE "force_handles_lowercase"
122 #define KEY_LDAP_ENABLE "ldap_enable"
125 #define KEY_LDAP_URI "ldap_uri"
126 #define KEY_LDAP_BASE "ldap_base"
127 #define KEY_LDAP_DN_FMT "ldap_dn_fmt"
128 #define KEY_LDAP_VERSION "ldap_version"
129 #define KEY_LDAP_AUTOCREATE "ldap_autocreate"
130 #define KEY_LDAP_ADMIN_DN "ldap_admin_dn"
131 #define KEY_LDAP_ADMIN_PASS "ldap_admin_pass"
132 #define KEY_LDAP_FIELD_ACCOUNT "ldap_field_account"
133 #define KEY_LDAP_FIELD_PASSWORD "ldap_field_password"
134 #define KEY_LDAP_FIELD_EMAIL "ldap_field_email"
135 #define KEY_LDAP_FIELD_OSLEVEL "ldap_field_oslevel"
136 #define KEY_LDAP_OBJECT_CLASSES "ldap_object_classes"
137 #define KEY_LDAP_OPER_GROUP_DN "ldap_oper_group_dn"
138 #define KEY_LDAP_OPER_GROUP_LEVEL "ldap_oper_group_level"
139 #define KEY_LDAP_FIELD_GROUP_MEMBER "ldap_field_group_member"
140 #define KEY_LDAP_TIMEOUT "ldap_timeout"
143 #define NICKSERV_VALID_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
145 #define NICKSERV_FUNC(NAME) MODCMD_FUNC(NAME)
146 #define OPTION_FUNC(NAME) int NAME(UNUSED_ARG(struct svccmd *cmd), struct userNode *user, struct handle_info *hi, UNUSED_ARG(unsigned int override), unsigned int argc, char *argv[])
147 typedef OPTION_FUNC(option_func_t
);
149 DEFINE_LIST(handle_info_list
, struct handle_info
*)
151 #define NICKSERV_MIN_PARMS(N) do { \
153 reply("MSG_MISSING_PARAMS", argv[0]); \
154 svccmd_send_help_brief(user, nickserv, cmd); \
158 struct userNode
*nickserv
;
159 struct userList curr_helpers
;
160 const char *handle_flags
= HANDLE_FLAGS
;
162 extern struct string_list
*autojoin_channels
;
163 static struct module *nickserv_module
;
164 static struct service
*nickserv_service
;
165 static struct log_type
*NS_LOG
;
166 dict_t nickserv_handle_dict
; /* contains struct handle_info* */
167 static dict_t nickserv_id_dict
; /* contains struct handle_info* */
168 static dict_t nickserv_nick_dict
; /* contains struct nick_info* */
169 static dict_t nickserv_opt_dict
; /* contains option_func_t* */
170 static dict_t nickserv_allow_auth_dict
; /* contains struct handle_info* */
171 static dict_t nickserv_email_dict
; /* contains struct handle_info_list*, indexed by email addr */
172 static char handle_inverse_flags
[256];
173 static unsigned int flag_access_levels
[32];
174 static const struct message_entry msgtab
[] = {
175 { "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." },
176 { "NSMSG_HANDLE_EXISTS", "Account $b%s$b is already registered." },
177 { "NSMSG_HANDLE_TOLONG", "The account name %s is too long. Account names must be %lu characters or less."},
178 { "NSMSG_PASSWORD_SHORT", "Your password must be at least %lu characters long." },
179 { "NSMSG_PASSWORD_ACCOUNT", "Your password may not be the same as your account name." },
180 { "NSMSG_PASSWORD_DICTIONARY", "Your password is too simple. You must choose a password that is not just a word or name." },
181 { "NSMSG_PASSWORD_READABLE", "Your password must have at least %lu digit(s), %lu capital letter(s), and %lu lower-case letter(s)." },
182 { "NSMSG_LDAP_FAIL", "There was a problem in contacting the account server (ldap): %s. Please try again later." },
183 { "NSMSG_LDAP_FAIL_ADD", "There was a problem in adding account %s to ldap: %s." },
184 { "NSMSG_LDAP_FAIL_SEND_EMAIL", "There was a problem in storing your email address in the account server (ldap): %s. Please try again later." },
185 { "NSMSG_LDAP_FAIL_GET_EMAIL", "There was a problem in retrieving your email address from the account server (ldap): %s. Please try again later." },
186 { "NSMSG_PARTIAL_REGISTER", "Account has been registered to you; nick was already registered to someone else." },
187 { "NSMSG_OREGISTER_VICTIM", "%s has registered a new account for you (named %s)." },
188 { "NSMSG_OREGISTER_H_SUCCESS", "Account has been registered." },
189 { "NSMSG_REGISTER_H_SUCCESS", "Account has been registered to you." },
190 { "NSMSG_REGISTER_HN_SUCCESS", "Account and nick have been registered to you." },
191 { "NSMSG_REQUIRE_OPER", "You must be an $bIRC Operator$b to register the first account." },
192 { "NSMSG_ROOT_HANDLE", "Account %s has been granted $broot-level privileges$b." },
193 { "NSMSG_USE_COOKIE_REGISTER", "To activate your account, you must check your email for the \"cookie\" that has been mailed to it. When you have it, use the $bcookie$b command to complete registration." },
194 { "NSMSG_USE_COOKIE_RESETPASS", "A cookie has been mailed to your account's email address. You must check your email and use the $bcookie$b command to confirm the password change." },
195 { "NSMSG_USE_COOKIE_EMAIL_1", "A cookie has been mailed to the new address you requested. To finish setting your email address, please check your email for the cookie and use the $bcookie$b command to verify." },
196 { "NSMSG_USE_COOKIE_EMAIL_2", "A cookie has been generated, and half mailed to each your old and new addresses. To finish changing your email address, please check your email for the cookie and use the $bcookie$b command to verify." },
197 { "NSMSG_USE_COOKIE_AUTH", "A cookie has been generated and sent to your email address. Once you have checked your email and received the cookie, auth using the $bcookie$b command." },
198 { "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." },
199 { "NSMSG_EMAIL_UNACTIVATED", "That email address already has an unused cookie outstanding. Please use the cookie or wait for it to expire." },
200 { "NSMSG_NO_COOKIE", "Your account does not have any cookie issued right now." },
201 { "NSMSG_NO_COOKIE_FOREIGN", "The account $b%s$b does not have any cookie issued right now." },
202 { "NSMSG_CANNOT_COOKIE", "You cannot use that kind of cookie when you are logged in." },
203 { "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." },
204 { "NSMSG_HANDLE_ACTIVATED", "Your account is now activated (with the password you entered when you registered). You are now authenticated to your account." },
205 { "NSMSG_PASSWORD_CHANGED", "You have successfully changed your password to what you requested with the $bresetpass$b command." },
206 { "NSMSG_EMAIL_PROHIBITED", "%s may not be used as an email address: %s" },
207 { "NSMSG_EMAIL_OVERUSED", "That email address already has an account. Use RESETPASS if you forgot your password." },
208 { "NSMSG_EMAIL_SAME", "That is the email address already there; no need to change it." },
209 { "NSMSG_EMAIL_CHANGED", "You have successfully changed your email address." },
210 { "NSMSG_BAD_COOKIE_TYPE", "Your account had bad cookie type %d; sorry. I am confused. Please report this bug." },
211 { "NSMSG_MUST_TIME_OUT", "You must wait for cookies of that type to time out." },
212 { "NSMSG_ATE_COOKIE", "I ate the cookie for your account. You may now have another." },
213 { "NSMSG_ATE_FOREIGN_COOKIE", "I ate the cookie for account $b%s$b. It may now have another." },
214 { "NSMSG_USE_RENAME", "You are already authenticated to account $b%s$b -- contact the support staff to rename your account." },
215 { "NSMSG_ALREADY_REGISTERING", "You have already used $bREGISTER$b once this session; you may not use it again." },
216 { "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 *@*)." },
217 { "NSMSG_NICK_NOT_REGISTERED", "Nick $b%s$b has not been registered to any account." },
218 { "NSMSG_HANDLE_NOT_FOUND", "Could not find your account -- did you register yet?" },
219 { "NSMSG_ALREADY_AUTHED", "You are already authed to account $b%s$b; you must reconnect to auth to a different account." },
220 { "NSMSG_USE_AUTHCOOKIE", "Your hostmask is not valid for account $b%1$s$b. Please use the $bauthcookie$b command to grant yourself access. (/msg $S authcookie %1$s)" },
221 { "NSMSG_HOSTMASK_INVALID", "Your hostmask is not valid for account $b%s$b." },
222 { "NSMSG_USER_IS_SERVICE", "$b%s$b is a network service; you can only use that command on real users." },
223 { "NSMSG_USER_PREV_AUTH", "$b%s$b is already authenticated." },
224 { "NSMSG_USER_PREV_STAMP", "$b%s$b has authenticated to an account once and cannot authenticate again." },
225 { "NSMSG_BAD_MAX_LOGINS", "MaxLogins must be at most %d." },
226 { "NSMSG_BAD_ADVANCED", "Advanced must be either 1 to enable it or 0 to disable it." },
227 { "NSMSG_LANGUAGE_NOT_FOUND", "Language $b%s$b is not supported; $b%s$b was the closest available match." },
228 { "NSMSG_MAX_LOGINS", "Your account already has its limit of %d user(s) logged in." },
229 { "NSMSG_STAMPED_REGISTER", "You have already authenticated to an account once this session; you may not register a new account." },
230 { "NSMSG_STAMPED_AUTH", "You have already authenticated to an account once this session; you may not authenticate to another." },
231 { "NSMSG_STAMPED_RESETPASS", "You have already authenticated to an account once this session; you may not reset your password to authenticate again." },
232 { "NSMSG_STAMPED_AUTHCOOKIE", "You have already authenticated to an account once this session; you may not use a cookie to authenticate to another account." },
233 { "NSMSG_TITLE_INVALID", "Titles may contain only a-z, A-Z, 0-9, and '-'. Please choose another." },
234 { "NSMSG_TITLE_TRUNCATED", "That title combined with the user's account name would result in a truncated host; please choose a shorter title." },
235 { "NSMSG_FAKEHOST_INVALID", "Fake hosts must be shorter than %d characters and cannot start with a dot." },
236 { "NSMSG_HANDLEINFO_ON", "$bAccount Information for %s$b" },
237 { "NSMSG_HANDLEINFO_END", "----------End of Account Info-----------" },
238 { "NSMSG_HANDLEINFO_ID", "Account ID: %lu" },
239 { "NSMSG_HANDLEINFO_REGGED", "Registered on: %s" },
240 { "NSMSG_HANDLEINFO_LASTSEEN", "Last seen: %s" },
241 { "NSMSG_HANDLEINFO_LASTSEEN_NOW", "Last seen: Right now!" },
242 { "NSMSG_HANDLEINFO_KARMA", "Karma: %d" },
243 { "NSMSG_HANDLEINFO_VACATION", "On vacation." },
244 { "NSMSG_HANDLEINFO_EMAIL_ADDR", "Email address: %s" },
245 { "NSMSG_HANDLEINFO_COOKIE_ACTIVATION", "Cookie: There is currently an activation cookie issued for this account" },
246 { "NSMSG_HANDLEINFO_COOKIE_PASSWORD", "Cookie: There is currently a password change cookie issued for this account" },
247 { "NSMSG_HANDLEINFO_COOKIE_EMAIL", "Cookie: There is currently an email change cookie issued for this account" },
248 { "NSMSG_HANDLEINFO_COOKIE_ALLOWAUTH", "Cookie: There is currently an allowauth cookie issued for this account" },
249 { "NSMSG_HANDLEINFO_COOKIE_UNKNOWN", "Cookie: There is currently an unknown cookie issued for this account" },
250 { "NSMSG_HANDLEINFO_INFOLINE", "Infoline: %s" },
251 { "NSMSG_HANDLEINFO_FLAGS", "Flags: %s" },
252 { "NSMSG_HANDLEINFO_EPITHET", "Epithet: %s" },
253 { "NSMSG_HANDLEINFO_NOTE", "Note (by %s on %s): %s " },
254 { "NSMSG_HANDLEINFO_FAKEHOST", "Fake host: %s" },
255 { "NSMSG_INVALID_KARMA", "$b%s$b is not a valid karma modifier." },
256 { "NSMSG_SET_KARMA", "$bKARMA: $b%d$b" },
257 { "NSMSG_HANDLEINFO_LAST_HOST", "Last quit hostmask: %s" },
258 { "NSMSG_HANDLEINFO_LAST_HOST_UNKNOWN", "Last quit hostmask: Unknown" },
259 { "NSMSG_HANDLEINFO_NICKS", "Nickname(s): %s" },
260 { "NSMSG_HANDLEINFO_MASKS", "Hostmask(s): %s" },
261 { "NSMSG_HANDLEINFO_SSLFPS", "SSL Fingerprints(s): %s" },
262 { "NSMSG_HANDLEINFO_IGNORES", "Ignore(s): %s" },
263 { "NSMSG_HANDLEINFO_CHANNELS", "Channel(s): %s" },
264 { "NSMSG_HANDLEINFO_CURRENT", "Current nickname(s): %s" },
265 { "NSMSG_HANDLEINFO_DNR", "Do-not-register (by %s): %s" },
266 { "NSMSG_USERINFO_AUTHED_AS", "$b%s$b is authenticated to account $b%s$b." },
267 { "NSMSG_USERINFO_NOT_AUTHED", "$b%s$b is not authenticated to any account." },
268 { "NSMSG_NICKINFO_OWNER", "Nick $b%s$b is owned by account $b%s$b." },
269 { "NSMSG_PASSWORD_INVALID", "Incorrect password; please try again." },
270 { "NSMSG_PLEASE_SET_EMAIL", "We now require email addresses for users. Please use the $bset email$b command to set your email address!" },
271 { "NSMSG_WEAK_PASSWORD", "WARNING: You are using a password that is considered weak (easy to guess). It is STRONGLY recommended you change it (now, if not sooner) by typing \"/msg $S@$s PASS oldpass newpass\" (with your current password and a new password)." },
272 { "NSMSG_HANDLE_SUSPENDED", "Your $b$N$b account has been suspended; you may not use it." },
273 { "NSMSG_AUTH_SUCCESS", "I recognize you." },
274 { "NSMSG_ALLOWAUTH_STAFF", "$b%s$b is a helper or oper; please use $bstaff$b after the account name to allowauth." },
275 { "NSMSG_AUTH_ALLOWED", "User $b%s$b may now authenticate to account $b%s$b." },
276 { "NSMSG_AUTH_ALLOWED_MSG", "You may now authenticate to account $b%s$b by typing $b/msg $N@$s auth %s password$b (using your password). If you will be using this computer regularly, please type $b/msg $N addmask$b (AFTER you auth) to permanently add your hostmask." },
277 { "NSMSG_AUTH_ALLOWED_EMAIL", "You may also (after you auth) type $b/msg $N set email user@your.isp$b to set an email address. This will let you use the $bauthcookie$b command to be authenticated in the future." },
278 { "NSMSG_AUTH_NORMAL_ONLY", "User $b%s$b may now only authenticate to accounts with matching hostmasks." },
279 { "NSMSG_AUTH_UNSPECIAL", "User $b%s$b did not have any special auth allowance." },
280 { "NSMSG_MUST_AUTH", "You must be authenticated first." },
281 { "NSMSG_TOO_MANY_NICKS", "You have already registered the maximum permitted number of nicks." },
282 { "NSMSG_NICK_EXISTS", "Nick $b%s$b already registered." },
283 { "NSMSG_REGNICK_SUCCESS", "Nick $b%s$b has been registered to you." },
284 { "NSMSG_OREGNICK_SUCCESS", "Nick $b%s$b has been registered to account $b%s$b." },
285 { "NSMSG_PASS_SUCCESS", "Password changed." },
286 { "NSMSG_MASK_INVALID", "$b%s$b is an invalid hostmask." },
287 { "NSMSG_ADDMASK_ALREADY", "$b%s$b is already a hostmask in your account." },
288 { "NSMSG_ADDMASK_SUCCESS", "Hostmask %s added." },
289 { "NSMSG_ADDIGNORE_ALREADY", "$b%s$b is already an ignored hostmask in your account." },
290 { "NSMSG_ADDIGNORE_SUCCESS", "Hostmask %s added." },
291 { "NSMSG_ADDSSLFP_ALREADY", "$b%s$b is already an SSL fingerprint in your account." },
292 { "NSMSG_ADDSSLFP_SUCCESS", "SSL fingerprint %s added." },
293 { "NSMSG_DELMASK_NOTLAST", "You may not delete your last hostmask." },
294 { "NSMSG_DELMASK_SUCCESS", "Hostmask %s deleted." },
295 { "NSMSG_DELMASK_NOT_FOUND", "Unable to find mask to be deleted." },
296 { "NSMSG_DELSSLFP_SUCCESS", "SSL fingerprint %s deleted." },
297 { "NSMSG_DELSSLFP_NOT_FOUND", "Unable to find SSL fingerprint to be deleted." },
298 { "NSMSG_OPSERV_LEVEL_BAD", "You may not promote another oper above your level." },
299 { "NSMSG_USE_CMD_PASS", "Please use the PASS command to change your password." },
300 { "NSMSG_UNKNOWN_NICK", "I know nothing about nick $b%s$b." },
301 { "NSMSG_NOT_YOUR_NICK", "The nick $b%s$b is not registered to you." },
302 { "NSMSG_NICK_USER_YOU", "I will not let you kill yourself." },
303 { "NSMSG_UNREGNICK_SUCCESS", "Nick $b%s$b has been unregistered." },
304 { "NSMSG_UNREGISTER_SUCCESS", "Account $b%s$b has been unregistered." },
305 { "NSMSG_UNREGISTER_NICKS_SUCCESS", "Account $b%s$b and all its nicks have been unregistered." },
306 { "NSMSG_UNREGISTER_MUST_FORCE", "Account $b%s$b is not inactive or has special flags set; use FORCE to unregister it." },
307 { "NSMSG_UNREGISTER_CANNOT_FORCE", "Account $b%s$b is not inactive or has special flags set; have an IRCOp use FORCE to unregister it." },
308 { "NSMSG_UNREGISTER_NODELETE", "Account $b%s$b is protected from unregistration." },
309 { "NSMSG_HANDLE_STATS", "There are %d nicks registered to your account." },
310 { "NSMSG_HANDLE_NONE", "You are not authenticated against any account." },
311 { "NSMSG_GLOBAL_STATS", "There are %d accounts and %d nicks registered globally." },
312 { "NSMSG_GLOBAL_STATS_NONICK", "There are %d accounts registered." },
313 { "NSMSG_CANNOT_GHOST_SELF", "You may not ghost-kill yourself." },
314 { "NSMSG_CANNOT_GHOST_USER", "$b%s$b is not authed to your account; you may not ghost-kill them." },
315 { "NSMSG_GHOST_KILLED", "$b%s$b has been killed as a ghost." },
316 { "NSMSG_ON_VACATION", "You are now on vacation. Your account will be preserved until you authenticate again." },
317 { "NSMSG_NO_ACCESS", "Access denied." },
318 { "NSMSG_INVALID_FLAG", "$b%c$b is not a valid $N account flag." },
319 { "NSMSG_SET_FLAG", "Applied flags $b%s$b to %s's $N account." },
320 { "NSMSG_FLAG_PRIVILEGED", "You have insufficient access to set flag %c." },
321 { "NSMSG_DB_UNREADABLE", "Unable to read database file %s; check the log for more information." },
322 { "NSMSG_DB_MERGED", "$N merged DB from %s (in "FMT_TIME_T
".%03lu seconds)." },
323 { "NSMSG_HANDLE_CHANGED", "$b%s$b's account name has been changed to $b%s$b." },
324 { "NSMSG_BAD_HANDLE", "Account $b%s$b is not allowed because it is reserved, is too long, or contains invalid characters." },
325 { "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." },
326 { "NSMSG_BAD_EMAIL_ADDR", "Please use a well-formed email address." },
327 { "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." },
328 { "NSMSG_ACCOUNT_SEARCH_RESULTS", "The following accounts were found:" },
329 { "NSMSG_SEARCH_MATCH", "Match: %s" },
330 { "NSMSG_INVALID_ACTION", "%s is an invalid search action." },
331 { "NSMSG_CANNOT_MERGE_SELF", "You cannot merge account $b%s$b with itself." },
332 { "NSMSG_HANDLES_MERGED", "Merged account $b%s$b into $b%s$b." },
333 { "NSMSG_RECLAIM_WARN", "%s is a registered nick - you must auth to account %s or change your nick." },
334 { "NSMSG_RECLAIM_HOWTO", "To auth to account %s you must use /msg %s@%s AUTH %s <password>" },
335 { "NSMSG_RECLAIM_KILL", "Unauthenticated user of nick." },
336 { "NSMSG_RECLAIMED_NONE", "You cannot manually reclaim a nick." },
337 { "NSMSG_RECLAIMED_WARN", "Sent a request for %s to change their nick." },
338 { "NSMSG_RECLAIMED_SVSNICK", "Forcibly changed %s's nick." },
339 { "NSMSG_RECLAIMED_KILL", "Disconnected %s from the network." },
340 { "NSMSG_CLONE_AUTH", "Warning: %s (%s@%s) authed to your account." },
341 { "NSMSG_SETTING_LIST", "$b$N account settings$b" },
342 { "NSMSG_SETTING_LIST_HEADER", "----------------------------------------" },
343 { "NSMSG_SETTING_LIST_END", "-------------End Of Settings------------" },
344 { "NSMSG_INVALID_OPTION", "$b%s$b is an invalid account setting." },
345 { "NSMSG_INVALID_ANNOUNCE", "$b%s$b is an invalid announcements value." },
346 { "NSMSG_SET_INFO", "$bINFO: $b%s" },
347 { "NSMSG_SET_WIDTH", "$bWIDTH: $b%d" },
348 { "NSMSG_SET_TABLEWIDTH", "$bTABLEWIDTH: $b%d" },
349 { "NSMSG_SET_COLOR", "$bCOLOR: $b%s" },
350 { "NSMSG_SET_PRIVMSG", "$bPRIVMSG: $b%s" },
351 { "NSMSG_SET_STYLE", "$bSTYLE: $b%s" },
352 { "NSMSG_SET_ANNOUNCEMENTS", "$bANNOUNCEMENTS: $b%s" },
353 { "NSMSG_SET_AUTOHIDE", "$bAUTOHIDE: $b%s" },
354 { "NSMSG_SET_PASSWORD", "$bPASSWORD: $b%s" },
355 { "NSMSG_SET_FLAGS", "$bFLAGS: $b%s" },
356 { "NSMSG_SET_EMAIL", "$bEMAIL: $b%s" },
357 { "NSMSG_SET_MAXLOGINS", "$bMAXLOGINS: $b%d" },
358 { "NSMSG_SET_ADVANCED", "$bADVANCED: $b%s" },
359 { "NSMSG_SET_LANGUAGE", "$bLANGUAGE: $b%s" },
360 { "NSMSG_SET_LEVEL", "$bLEVEL: $b%d" },
361 { "NSMSG_SET_EPITHET", "$bEPITHET: $b%s" },
362 { "NSMSG_SET_NOTE", "$bNOTE: $b%s"},
363 { "NSMSG_SET_TITLE", "$bTITLE: $b%s" },
364 { "NSMSG_SET_FAKEHOST", "$bFAKEHOST: $b%s" },
366 { "NSMSG_AUTO_OPER", "You have been auto-opered" },
367 { "NSMSG_AUTO_OPER_ADMIN", "You have been auto-admined" },
369 { "NSEMAIL_ACTIVATION_SUBJECT", "Account verification for %s" },
370 { "NSEMAIL_ACTIVATION_BODY",
371 "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"
373 "To verify your email address and complete the account registration, log on to %1$s and type the following command:\n"
374 "/msg %3$s@%4$s COOKIE %5$s %2$s\n"
375 "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"
376 "/msg %3$s@%4$s AUTH %5$s your-password\n"
377 "(Please remember to fill in 'your-password' with the actual password you gave to us when you registered.)\n"
378 "OR configure Login-On-Connect (see http://www.afternet.org/login-on-connect for instructions) to connect pre-logged in every time.\n"
380 "If you did NOT request this account, you do not need to do anything.\n"
381 "Please contact the %1$s staff if you have questions, and be sure to check our website." },
382 { "NSEMAIL_ACTIVATION_BODY_WEB",
383 "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"
385 "To verify your email address and complete the account registration, visit the following URL:\n"
386 "http://www.afternet.org/index.php?option=com_registration&task=activate&username=%5$s&cookie=%2$s\n"
388 "If you did NOT request this account, you do not need to do anything.\n"
389 "Please contact the %1$s staff if you have questions, and be sure to check our website." },
390 { "NSEMAIL_PASSWORD_CHANGE_SUBJECT", "Password change verification on %s" },
391 { "NSEMAIL_PASSWORD_CHANGE_BODY",
392 "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"
393 "To complete the password change, log on to %1$s and type the following command:\n"
394 "/msg %3$s@%4$s COOKIE %5$s %2$s\n"
395 "If you did NOT request your password to be changed, you do not need to do anything.\n"
396 "Please contact the %1$s staff if you have questions." },
397 { "NSEMAIL_PASSWORD_CHANGE_BODY_WEB",
398 "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"
399 "To complete the password change, click the following URL:\n"
400 "http://www.afternet.org/index.php?option=com_registration&task=passcookie&username=%5$s&cookie=%2$s\n"
401 "If you did NOT request your password to be changed, you do not need to do anything.\n"
402 "Please contact the %1$s staff if you have questions." },
403 { "NSEMAIL_EMAIL_CHANGE_SUBJECT", "Email address change verification for %s" },
404 #ifdef stupid_verify_old_email
405 { "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." },
406 { "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." },
408 { "NSEMAIL_EMAIL_VERIFY_SUBJECT", "Email address verification for %s" },
409 { "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." },
410 { "NSEMAIL_ALLOWAUTH_SUBJECT", "Authentication allowed for %s" },
411 { "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." },
412 { "NSMSG_NOT_VALID_FAKEHOST_DOT", "$b%s$b is not a valid vhost. (needs at least one dot)" },
413 { "NSMSG_NOT_VALID_FAKEHOST_AT", "$b%s$b is not a valid vhost. (it can not have a '@')" },
414 { "NSMSG_DENIED_FAKEHOST_WORD", "Access denied because there's a prohibited word in $b%s$b (%s)." },
415 { "NSMSG_NOT_VALID_FAKEHOST_LEN", "$b%s$b is not a valid vhost. (can only be 63 characters)" },
416 { "NSMSG_NOT_VALID_FAKEHOST_TLD_LEN", "$b%s$b is not a valid vhost. (TLD can only be 4 characters and less)" },
417 { "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." },
418 { "CHECKPASS_YES", "Yes." },
419 { "CHECKPASS_NO", "No." },
420 { "CHECKEMAIL_NOT_SET", "No email set." },
421 { "CHECKEMAIL_YES", "Yes." },
422 { "CHECKEMAIL_NO", "No." },
423 { "NSMSG_DEFCON_NO_NEW_NICKS", "You cannot register new %s at this time, please try again soon" },
427 static void nickserv_reclaim(struct userNode
*user
, struct nick_info
*ni
, enum reclaim_action action
);
428 static void nickserv_reclaim_p(void *data
);
429 static int nickserv_addmask(struct userNode
*user
, struct handle_info
*hi
, const char *mask
);
431 struct nickserv_config nickserv_conf
;
433 /* We have 2^32 unique account IDs to use. */
434 unsigned long int highest_id
= 0;
437 canonicalize_hostmask(char *mask
)
439 char *out
= mask
, *temp
;
440 if ((temp
= strchr(mask
, '!'))) {
442 while (*temp
) *out
++ = *temp
++;
448 static struct handle_note
*
449 nickserv_add_note(const char *setter
, time_t date
, const char *text
)
451 struct handle_note
*note
= calloc(1, sizeof(*note
) + strlen(text
));
453 strncpy(note
->setter
, setter
, sizeof(note
->setter
)-1);
455 memcpy(note
->note
, text
, strlen(text
));
459 static struct handle_info
*
460 register_handle(const char *handle
, const char *passwd
, UNUSED_ARG(unsigned long id
))
462 struct handle_info
*hi
;
464 hi
= calloc(1, sizeof(*hi
));
465 hi
->userlist_style
= nickserv_conf
.default_style
? nickserv_conf
.default_style
: HI_DEFAULT_STYLE
;
466 hi
->announcements
= '?';
467 hi
->handle
= strdup(handle
);
468 safestrncpy(hi
->passwd
, passwd
, sizeof(hi
->passwd
));
470 dict_insert(nickserv_handle_dict
, hi
->handle
, hi
);
476 register_nick(const char *nick
, struct handle_info
*owner
)
478 struct nick_info
*ni
;
479 ni
= malloc(sizeof(struct nick_info
));
480 safestrncpy(ni
->nick
, nick
, sizeof(ni
->nick
));
482 ni
->next
= owner
->nicks
;
484 dict_insert(nickserv_nick_dict
, ni
->nick
, ni
);
488 delete_nick(struct nick_info
*ni
)
490 struct nick_info
*last
, *next
;
491 struct userNode
*user
;
492 /* Check to see if we should mark a user as unregistered. */
493 if ((user
= GetUserH(ni
->nick
)) && IsReggedNick(user
)) {
494 user
->modes
&= ~FLAGS_REGNICK
;
497 /* Remove ni from the nick_info linked list. */
498 if (ni
== ni
->owner
->nicks
) {
499 ni
->owner
->nicks
= ni
->next
;
501 last
= ni
->owner
->nicks
;
507 last
->next
= next
->next
;
509 dict_remove(nickserv_nick_dict
, ni
->nick
);
512 static unreg_func_t
*unreg_func_list
;
513 static void **unreg_func_list_extra
;
514 static unsigned int unreg_func_size
= 0, unreg_func_used
= 0;
517 reg_unreg_func(unreg_func_t func
, void *extra
)
519 if (unreg_func_used
== unreg_func_size
) {
520 if (unreg_func_size
) {
521 unreg_func_size
<<= 1;
522 unreg_func_list
= realloc(unreg_func_list
, unreg_func_size
*sizeof(unreg_func_t
));
523 unreg_func_list_extra
= realloc(unreg_func_list_extra
, unreg_func_size
*sizeof(void*));
526 unreg_func_list
= malloc(unreg_func_size
*sizeof(unreg_func_t
));
527 unreg_func_list_extra
= malloc(unreg_func_size
*sizeof(void*));
530 unreg_func_list
[unreg_func_used
] = func
;
531 unreg_func_list_extra
[unreg_func_used
++] = extra
;
535 nickserv_free_cookie(void *data
)
537 struct handle_cookie
*cookie
= data
;
538 if (cookie
->hi
) cookie
->hi
->cookie
= NULL
;
539 if (cookie
->data
) free(cookie
->data
);
544 free_handle_info(void *vhi
)
546 struct handle_info
*hi
= vhi
;
548 free_string_list(hi
->masks
);
549 free_string_list(hi
->sslfps
);
550 free_string_list(hi
->ignores
);
554 delete_nick(hi
->nicks
);
560 timeq_del(hi
->cookie
->expires
, nickserv_free_cookie
, hi
->cookie
, 0);
561 nickserv_free_cookie(hi
->cookie
);
563 if (hi
->email_addr
) {
564 struct handle_info_list
*hil
= dict_find(nickserv_email_dict
, hi
->email_addr
, NULL
);
565 handle_info_list_remove(hil
, hi
);
567 dict_remove(nickserv_email_dict
, hi
->email_addr
);
572 static void set_user_handle_info(struct userNode
*user
, struct handle_info
*hi
, int stamp
);
575 nickserv_unregister_handle(struct handle_info
*hi
, struct userNode
*notify
, struct userNode
*bot
)
578 struct userNode
*uNode
;
581 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
583 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
584 if( (rc
= ldap_delete_account(hi
->handle
)) != LDAP_SUCCESS
) {
586 send_message(notify
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
588 if(rc
!= LDAP_NO_SUCH_OBJECT
)
589 return false; /* if theres noone there to delete, its kinda ok, right ?:) */
594 for (n
=0; n
<unreg_func_used
; n
++)
595 unreg_func_list
[n
](notify
, hi
, unreg_func_list_extra
[n
]);
597 if (nickserv_conf
.sync_log
) {
598 uNode
= GetUserH(hi
->users
->nick
);
602 set_user_handle_info(hi
->users
, NULL
, 0);
605 if (nickserv_conf
.disable_nicks
)
606 send_message(notify
, bot
, "NSMSG_UNREGISTER_SUCCESS", hi
->handle
);
608 send_message(notify
, bot
, "NSMSG_UNREGISTER_NICKS_SUCCESS", hi
->handle
);
611 if (nickserv_conf
.sync_log
)
612 SyncLog("UNREGISTER %s", hi
->handle
);
614 dict_remove(nickserv_handle_dict
, hi
->handle
);
619 get_handle_info(const char *handle
)
621 return dict_find(nickserv_handle_dict
, handle
, 0);
625 get_nick_info(const char *nick
)
627 return nickserv_conf
.disable_nicks
? 0 : dict_find(nickserv_nick_dict
, nick
, 0);
631 find_handle_in_channel(struct chanNode
*channel
, struct handle_info
*handle
, struct userNode
*except
)
636 for (nn
=0; nn
<channel
->members
.used
; ++nn
) {
637 mn
= channel
->members
.list
[nn
];
638 if ((mn
->user
!= except
) && (mn
->user
->handle_info
== handle
))
645 oper_has_access(struct userNode
*user
, struct userNode
*bot
, unsigned int min_level
, unsigned int quiet
) {
646 if (!user
->handle_info
) {
648 send_message(user
, bot
, "MSG_AUTHENTICATE");
652 if (!IsOper(user
) && (!IsHelping(user
) || min_level
)) {
654 send_message(user
, bot
, "NSMSG_NO_ACCESS");
658 if (HANDLE_FLAGGED(user
->handle_info
, OPER_SUSPENDED
)) {
660 send_message(user
, bot
, "MSG_OPER_SUSPENDED");
664 if (user
->handle_info
->opserv_level
< min_level
) {
666 send_message(user
, bot
, "NSMSG_NO_ACCESS");
674 is_valid_handle(const char *handle
)
676 struct userNode
*user
;
677 /* cant register a juped nick/service nick as handle, to prevent confusion */
678 user
= GetUserH(handle
);
679 if (user
&& IsLocal(user
))
681 /* check against maximum length */
682 if (strlen(handle
) > NICKSERV_HANDLE_LEN
)
684 /* for consistency, only allow account names that could be nicks */
685 if (!is_valid_nick(handle
))
687 /* disallow account names that look like bad words */
688 if (opserv_bad_channel(handle
))
690 /* test either regex or containing all valid chars */
691 if (nickserv_conf
.valid_handle_regex_set
) {
692 int err
= regexec(&nickserv_conf
.valid_handle_regex
, handle
, 0, 0, 0);
695 buff
[regerror(err
, &nickserv_conf
.valid_handle_regex
, buff
, sizeof(buff
))] = 0;
696 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
700 return !handle
[strspn(handle
, NICKSERV_VALID_CHARS
)];
705 is_registerable_nick(const char *nick
)
707 struct userNode
*user
;
708 /* cant register a juped nick/service nick as nick, to prevent confusion */
709 user
= GetUserH(nick
);
710 if (user
&& IsLocal(user
))
712 /* for consistency, only allow nicks names that could be nicks */
713 if (!is_valid_nick(nick
))
715 /* disallow nicks that look like bad words */
716 if (opserv_bad_channel(nick
))
719 if (strlen(nick
) > NICKLEN
)
721 /* test either regex or as valid handle */
722 if (nickserv_conf
.valid_nick_regex_set
) {
723 int err
= regexec(&nickserv_conf
.valid_nick_regex
, nick
, 0, 0, 0);
726 buff
[regerror(err
, &nickserv_conf
.valid_nick_regex
, buff
, sizeof(buff
))] = 0;
727 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
733 /* this has been replaced with one in tools.c
736 is_valid_email_addr(const char *email)
738 return strchr(email, '@') != NULL;
744 visible_email_addr(struct userNode
*user
, struct handle_info
*hi
)
746 if (hi
->email_addr
) {
747 if (oper_has_access(user
, nickserv
, nickserv_conf
.email_visible_level
, 1)) {
748 return hi
->email_addr
;
758 smart_get_handle_info(struct userNode
*service
, struct userNode
*user
, const char *name
)
760 struct handle_info
*hi
;
761 struct userNode
*target
;
765 if (!(hi
= get_handle_info(++name
))) {
766 send_message(user
, service
, "MSG_HANDLE_UNKNOWN", name
);
771 if (!(target
= GetUserH(name
))) {
772 send_message(user
, service
, "MSG_NICK_UNKNOWN", name
);
775 if (IsLocal(target
)) {
776 if (IsService(target
))
777 send_message(user
, service
, "NSMSG_USER_IS_SERVICE", target
->nick
);
779 send_message(user
, service
, "MSG_USER_AUTHENTICATE", target
->nick
);
782 if (!(hi
= target
->handle_info
)) {
783 send_message(user
, service
, "MSG_USER_AUTHENTICATE", target
->nick
);
791 oper_outranks(struct userNode
*user
, struct handle_info
*hi
) {
792 if (user
->handle_info
->opserv_level
> hi
->opserv_level
)
794 if (user
->handle_info
->opserv_level
== hi
->opserv_level
) {
795 if ((user
->handle_info
->opserv_level
== 1000)
796 || (user
->handle_info
== hi
)
797 || ((user
->handle_info
->opserv_level
== 0)
798 && !(HANDLE_FLAGGED(hi
, SUPPORT_HELPER
) || HANDLE_FLAGGED(hi
, NETWORK_HELPER
))
799 && HANDLE_FLAGGED(user
->handle_info
, HELPING
))) {
803 send_message(user
, nickserv
, "MSG_USER_OUTRANKED", hi
->handle
);
808 get_victim_oper(struct userNode
*user
, const char *target
)
810 struct handle_info
*hi
;
811 if (!(hi
= smart_get_handle_info(nickserv
, user
, target
)))
813 if (HANDLE_FLAGGED(user
->handle_info
, OPER_SUSPENDED
)) {
814 send_message(user
, nickserv
, "MSG_OPER_SUSPENDED");
817 return oper_outranks(user
, hi
) ? hi
: NULL
;
821 valid_user_for(struct userNode
*user
, struct handle_info
*hi
)
825 /* If no hostmasks on the account, allow it. */
826 if (!hi
->masks
->used
)
828 /* If any hostmask matches, allow it. */
829 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
830 if (user_matches_glob(user
, hi
->masks
->list
[ii
], 0, 0))
832 /* If they are allowauthed to this account, allow it (removing the aa). */
833 if (dict_find(nickserv_allow_auth_dict
, user
->nick
, NULL
) == hi
) {
834 dict_remove(nickserv_allow_auth_dict
, user
->nick
);
837 /* The user is not allowed to use this account. */
842 valid_user_sslfp(struct userNode
*user
, struct handle_info
*hi
)
846 if (!hi
->sslfps
->used
)
851 /* If any SSL fingerprint matches, allow it. */
852 for (ii
=0; ii
<hi
->sslfps
->used
; ii
++)
853 if (!irccasecmp(user
->sslfp
, hi
->sslfps
->list
[ii
]))
856 /* No valid SSL fingerprint found. */
861 is_secure_password(const char *handle
, const char *pass
, struct userNode
*user
)
864 unsigned int cnt_digits
= 0, cnt_upper
= 0, cnt_lower
= 0;
868 if (len
< nickserv_conf
.password_min_length
) {
870 send_message(user
, nickserv
, "NSMSG_PASSWORD_SHORT", nickserv_conf
.password_min_length
);
873 if (!irccasecmp(pass
, handle
)) {
875 send_message(user
, nickserv
, "NSMSG_PASSWORD_ACCOUNT");
878 dict_find(nickserv_conf
.weak_password_dict
, pass
, &p
);
881 send_message(user
, nickserv
, "NSMSG_PASSWORD_DICTIONARY");
884 for (i
=0; i
<len
; i
++) {
885 if (isdigit(pass
[i
]))
887 if (isupper(pass
[i
]))
889 if (islower(pass
[i
]))
892 if ((cnt_lower
< nickserv_conf
.password_min_lower
)
893 || (cnt_upper
< nickserv_conf
.password_min_upper
)
894 || (cnt_digits
< nickserv_conf
.password_min_digits
)) {
896 send_message(user
, nickserv
, "NSMSG_PASSWORD_READABLE", nickserv_conf
.password_min_digits
, nickserv_conf
.password_min_upper
, nickserv_conf
.password_min_lower
);
902 static auth_func_t
*auth_func_list
;
903 static void **auth_func_list_extra
;
904 static unsigned int auth_func_size
= 0, auth_func_used
= 0;
907 reg_auth_func(auth_func_t func
, void *extra
)
909 if (auth_func_used
== auth_func_size
) {
910 if (auth_func_size
) {
911 auth_func_size
<<= 1;
912 auth_func_list
= realloc(auth_func_list
, auth_func_size
*sizeof(auth_func_t
));
913 auth_func_list_extra
= realloc(auth_func_list_extra
, auth_func_size
*sizeof(void*));
916 auth_func_list
= malloc(auth_func_size
*sizeof(auth_func_t
));
917 auth_func_list_extra
= malloc(auth_func_size
*sizeof(void*));
920 auth_func_list
[auth_func_used
] = func
;
921 auth_func_list_extra
[auth_func_used
++] = extra
;
924 static handle_rename_func_t
*rf_list
;
925 static void **rf_list_extra
;
926 static unsigned int rf_list_size
, rf_list_used
;
929 reg_handle_rename_func(handle_rename_func_t func
, void *extra
)
931 if (rf_list_used
== rf_list_size
) {
934 rf_list
= realloc(rf_list
, rf_list_size
*sizeof(rf_list
[0]));
935 rf_list_extra
= realloc(rf_list_extra
, rf_list_size
*sizeof(void*));
938 rf_list
= malloc(rf_list_size
*sizeof(rf_list
[0]));
939 rf_list_extra
= malloc(rf_list_size
*sizeof(void*));
942 rf_list
[rf_list_used
] = func
;
943 rf_list_extra
[rf_list_used
++] = extra
;
947 generate_fakehost(struct handle_info
*handle
)
949 struct userNode
*target
;
950 extern const char *hidden_host_suffix
;
951 static char buffer
[HOSTLEN
+1];
955 if (!handle
->fakehost
) {
956 data
= conf_get_data("server/hidden_host_type", RECDB_QSTRING
);
961 snprintf(buffer
, sizeof(buffer
), "%s.%s", handle
->handle
, hidden_host_suffix
);
962 else if (style
== 2) {
963 /* Due to the way fakehost is coded theres no way i can
964 get the exact user, so for now ill just take the first
966 for (target
= handle
->users
; target
; target
= target
->next_authed
)
969 snprintf(buffer
, sizeof(buffer
), "%s", target
->crypthost
);
972 } else if (handle
->fakehost
[0] == '.') {
973 /* A leading dot indicates the stored value is actually a title. */
974 snprintf(buffer
, sizeof(buffer
), "%s.%s.%s", handle
->handle
, handle
->fakehost
+1, nickserv_conf
.titlehost_suffix
);
977 return handle
->fakehost
;
981 apply_fakehost(struct handle_info
*handle
)
983 struct userNode
*target
;
988 fake
= generate_fakehost(handle
);
989 for (target
= handle
->users
; target
; target
= target
->next_authed
)
990 assign_fakehost(target
, fake
, 1);
993 void send_func_list(struct userNode
*user
)
996 struct handle_info
*old_info
;
998 old_info
= user
->handle_info
;
1000 for (n
=0; n
<auth_func_used
; n
++)
1001 auth_func_list
[n
](user
, old_info
, auth_func_list_extra
[n
]);
1005 set_user_handle_info(struct userNode
*user
, struct handle_info
*hi
, int stamp
)
1008 struct handle_info
*old_info
;
1010 /* This can happen if somebody uses COOKIE while authed, or if
1011 * they re-auth to their current handle (which is silly, but users
1012 * are like that). */
1013 if (user
->handle_info
== hi
)
1016 if (user
->handle_info
) {
1017 struct userNode
*other
;
1020 userList_remove(&curr_helpers
, user
);
1022 /* remove from next_authed linked list */
1023 if (user
->handle_info
->users
== user
) {
1024 user
->handle_info
->users
= user
->next_authed
;
1025 } else if (user
->handle_info
->users
!= NULL
) {
1026 for (other
= user
->handle_info
->users
;
1027 other
->next_authed
!= user
;
1028 other
= other
->next_authed
) ;
1029 other
->next_authed
= user
->next_authed
;
1031 /* No users authed to the account - can happen if they get
1032 * killed for authing. */
1034 /* if nobody left on old handle, and they're not an oper, remove !god */
1035 if (!user
->handle_info
->users
&& !user
->handle_info
->opserv_level
)
1036 HANDLE_CLEAR_FLAG(user
->handle_info
, HELPING
);
1037 /* record them as being last seen at this time */
1038 user
->handle_info
->lastseen
= now
;
1039 /* and record their hostmask */
1040 snprintf(user
->handle_info
->last_quit_host
, sizeof(user
->handle_info
->last_quit_host
), "%s@%s", user
->ident
, user
->hostname
);
1042 old_info
= user
->handle_info
;
1043 user
->handle_info
= hi
;
1044 if (hi
&& !hi
->users
&& !hi
->opserv_level
)
1045 HANDLE_CLEAR_FLAG(hi
, HELPING
);
1047 /* Call auth handlers */
1048 if (!GetUserH(user
->nick
))
1052 struct nick_info
*ni
;
1054 HANDLE_CLEAR_FLAG(hi
, FROZEN
);
1055 if (nickserv_conf
.warn_clone_auth
) {
1056 struct userNode
*other
;
1057 for (other
= hi
->users
; other
; other
= other
->next_authed
)
1058 send_message(other
, nickserv
, "NSMSG_CLONE_AUTH", user
->nick
, user
->ident
, user
->hostname
);
1061 /* Add this auth to users list of current auths */
1062 user
->next_authed
= hi
->users
;
1065 /* Add to helpers list */
1066 if (IsHelper(user
) && !userList_contains(&curr_helpers
, user
))
1067 userList_append(&curr_helpers
, user
);
1069 /* Set the fakehost */
1070 if (hi
->fakehost
|| old_info
)
1074 #ifdef WITH_PROTOCOL_P10
1075 /* Stamp users with their account name. */
1076 char *id
= hi
->handle
;
1078 const char *id
= "???";
1080 /* Mark all the nicks registered to this
1081 * account as registered nicks
1082 * - Why not just this one? -rubin */
1083 if (!nickserv_conf
.disable_nicks
) {
1084 struct nick_info
*ni2
;
1085 for (ni2
= hi
->nicks
; ni2
; ni2
= ni2
->next
) {
1086 if (!irccasecmp(user
->nick
, ni2
->nick
)) {
1087 user
->modes
|= FLAGS_REGNICK
;
1092 /* send the account to the ircd */
1093 StampUser(user
, id
, hi
->registered
);
1096 /* Stop trying to kick this user off their nick */
1097 if ((ni
= get_nick_info(user
->nick
)) && (ni
->owner
== hi
))
1098 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
1100 /* We cannot clear the user's account ID, unfortunately. */
1101 user
->next_authed
= NULL
;
1104 /* Call auth handlers */
1105 if (GetUserH(user
->nick
)) {
1106 for (n
=0; n
<auth_func_used
; n
++) {
1107 auth_func_list
[n
](user
, old_info
, auth_func_list_extra
[n
]);
1114 static struct handle_info
*
1115 nickserv_register(struct userNode
*user
, struct userNode
*settee
, const char *handle
, const char *passwd
, int no_auth
)
1117 struct handle_info
*hi
;
1118 struct nick_info
*ni
;
1119 char crypted
[MD5_CRYPT_LENGTH
];
1121 if ((hi
= dict_find(nickserv_handle_dict
, handle
, NULL
))) {
1123 send_message(user
, nickserv
, "NSMSG_HANDLE_EXISTS", handle
);
1127 if(strlen(handle
) > 30)
1130 send_message(user
, nickserv
, "NSMSG_HANDLE_TOLONG", handle
, 30);
1134 if (!is_secure_password(handle
, passwd
, user
))
1137 cryptpass(passwd
, crypted
);
1139 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1141 rc
= ldap_do_add(handle
, (no_auth
? NULL
: crypted
), NULL
);
1142 if(LDAP_SUCCESS
!= rc
&& LDAP_ALREADY_EXISTS
!= rc
) {
1144 send_message(user
, nickserv
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
1149 hi
= register_handle(handle
, crypted
, 0);
1150 hi
->masks
= alloc_string_list(1);
1151 hi
->sslfps
= alloc_string_list(1);
1152 hi
->ignores
= alloc_string_list(1);
1154 hi
->language
= lang_C
;
1155 hi
->registered
= now
;
1157 hi
->flags
= HI_DEFAULT_FLAGS
;
1158 if (settee
&& !no_auth
)
1159 set_user_handle_info(settee
, hi
, 1);
1161 if (user
!= settee
) {
1163 send_message(user
, nickserv
, "NSMSG_OREGISTER_H_SUCCESS");
1165 else if (nickserv_conf
.disable_nicks
) {
1167 send_message(user
, nickserv
, "NSMSG_REGISTER_H_SUCCESS");
1170 else if (user
&& (ni
= dict_find(nickserv_nick_dict
, user
->nick
, NULL
))) {
1172 send_message(user
, nickserv
, "NSMSG_PARTIAL_REGISTER");
1177 if (is_registerable_nick(user
->nick
)) {
1178 register_nick(user
->nick
, hi
);
1179 send_message(user
, nickserv
, "NSMSG_REGISTER_HN_SUCCESS");
1183 if (settee
&& (user
!= settee
)) {
1185 send_message(settee
, nickserv
, "NSMSG_OREGISTER_VICTIM", user
->nick
, hi
->handle
);
1192 nickserv_bake_cookie(struct handle_cookie
*cookie
)
1194 cookie
->hi
->cookie
= cookie
;
1195 timeq_add(cookie
->expires
, nickserv_free_cookie
, cookie
);
1198 /* Contributed by the great sneep of afternet ;) */
1199 /* Since this gets used in a URL, we want to avoid stuff that confuses
1200 * email clients such as ] and ?. a-z, 0-9 only.
1202 void genpass(char *str
, int len
)
1207 for(i
= 0; i
< len
; i
++)
1211 c
= (char)((float)rand() / (float)RAND_MAX
* (float)256);
1212 } while(!((c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z') || (c
>= '0' && c
<= '9')));
1220 nickserv_make_cookie(struct userNode
*user
, struct handle_info
*hi
, enum cookie_type type
, const char *cookie_data
, int weblink
)
1222 struct handle_cookie
*cookie
;
1223 char subject
[128], body
[4096], *misc
;
1224 const char *netname
, *fmt
;
1228 send_message(user
, nickserv
, "NSMSG_COOKIE_LIVE", hi
->handle
);
1232 cookie
= calloc(1, sizeof(*cookie
));
1234 cookie
->type
= type
;
1235 cookie
->data
= cookie_data
? strdup(cookie_data
) : NULL
;
1237 cookie
->expires
= now
+ nickserv_conf
.cookie_timeout
;
1238 /* Adding dedicated password gen function for more control -Rubin */
1239 genpass(cookie
->cookie
, 10);
1241 *inttobase64(cookie->cookie, rand(), 5);
1242 *inttobase64(cookie->cookie+5, rand(), 5);
1245 netname
= nickserv_conf
.network_name
;
1248 switch (cookie
->type
) {
1250 hi
->passwd
[0] = 0; /* invalidate password */
1251 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_REGISTER");
1252 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_SUBJECT");
1253 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1256 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_BODY_WEB");
1258 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_BODY");
1260 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1263 case PASSWORD_CHANGE
:
1264 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_RESETPASS");
1265 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_SUBJECT");
1266 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1268 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_BODY_WEB");
1270 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_BODY");
1271 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1275 misc
= hi
->email_addr
;
1276 hi
->email_addr
= cookie
->data
;
1277 #ifdef stupid_verify_old_email
1279 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_EMAIL_2");
1280 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_SUBJECT");
1281 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1282 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_BODY_NEW");
1283 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
+COOKIELEN
/2, nickserv
->nick
, self
->name
, hi
->handle
, COOKIELEN
/2);
1284 mail_send(nickserv
, hi
, subject
, body
, 1);
1285 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_BODY_OLD");
1286 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
, COOKIELEN
/2, hi
->email_addr
);
1290 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_EMAIL_1");
1291 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_VERIFY_SUBJECT");
1292 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1293 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_VERIFY_BODY");
1294 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1295 mail_send(nickserv
, hi
, subject
, body
, 1);
1297 #ifdef stupid_verify_old_email
1300 hi
->email_addr
= misc
;
1303 fmt
= handle_find_message(hi
, "NSEMAIL_ALLOWAUTH_SUBJECT");
1304 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1305 fmt
= handle_find_message(hi
, "NSEMAIL_ALLOWAUTH_BODY");
1306 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1307 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_AUTH");
1310 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d in nickserv_make_cookie.", cookie
->type
);
1314 mail_send(nickserv
, hi
, subject
, body
, first_time
);
1315 nickserv_bake_cookie(cookie
);
1319 nickserv_eat_cookie(struct handle_cookie
*cookie
)
1321 cookie
->hi
->cookie
= NULL
;
1322 timeq_del(cookie
->expires
, nickserv_free_cookie
, cookie
, 0);
1323 nickserv_free_cookie(cookie
);
1327 nickserv_free_email_addr(void *data
)
1329 handle_info_list_clean(data
);
1334 nickserv_set_email_addr(struct handle_info
*hi
, const char *new_email_addr
)
1336 struct handle_info_list
*hil
;
1337 /* Remove from old handle_info_list ... */
1338 if (hi
->email_addr
&& (hil
= dict_find(nickserv_email_dict
, hi
->email_addr
, 0))) {
1339 handle_info_list_remove(hil
, hi
);
1340 if (!hil
->used
) dict_remove(nickserv_email_dict
, hil
->tag
);
1341 hi
->email_addr
= NULL
;
1343 /* Add to the new list.. */
1344 if (new_email_addr
) {
1345 if (!(hil
= dict_find(nickserv_email_dict
, new_email_addr
, 0))) {
1346 hil
= calloc(1, sizeof(*hil
));
1347 hil
->tag
= strdup(new_email_addr
);
1348 handle_info_list_init(hil
);
1349 dict_insert(nickserv_email_dict
, hil
->tag
, hil
);
1351 handle_info_list_append(hil
, hi
);
1352 hi
->email_addr
= hil
->tag
;
1356 static NICKSERV_FUNC(cmd_register
)
1359 struct handle_info
*hi
;
1360 const char *email_addr
, *password
;
1361 char syncpass
[MD5_CRYPT_LENGTH
];
1362 int no_auth
, weblink
;
1364 if (checkDefCon(DEFCON_NO_NEW_NICKS
) && !IsOper(user
)) {
1365 reply("NSMSG_DEFCON_NO_NEW_NICKS", nickserv_conf
.disable_nicks
? "accounts" : "nicknames");
1369 if (!IsOper(user
) && !dict_size(nickserv_handle_dict
)) {
1370 /* Require the first handle registered to belong to someone +o. */
1371 reply("NSMSG_REQUIRE_OPER");
1375 if (user
->handle_info
) {
1376 reply("NSMSG_USE_RENAME", user
->handle_info
->handle
);
1380 if (IsRegistering(user
)) {
1381 reply("NSMSG_ALREADY_REGISTERING");
1385 if (IsStamped(user
)) {
1386 /* Unauthenticated users might still have been stamped
1387 previously and could therefore have a hidden host;
1388 do not allow them to register a new account. */
1389 reply("NSMSG_STAMPED_REGISTER");
1393 NICKSERV_MIN_PARMS((unsigned)3 + nickserv_conf
.email_required
);
1395 if(nickserv_conf
.force_handles_lowercase
)
1396 irc_strtolower(argv
[1]);
1397 if (!is_valid_handle(argv
[1])) {
1398 reply("NSMSG_BAD_HANDLE", argv
[1]);
1403 if ((argc
>= 4) && nickserv_conf
.email_enabled
) {
1404 struct handle_info_list
*hil
;
1407 /* Remember email address. */
1408 email_addr
= argv
[3];
1410 /* Check that the email address looks valid.. */
1411 if (!valid_email(email_addr
)) {
1412 reply("NSMSG_BAD_EMAIL_ADDR");
1416 /* .. and that we are allowed to send to it. */
1417 if ((str
= mail_prohibited_address(email_addr
))) {
1418 reply("NSMSG_EMAIL_PROHIBITED", email_addr
, str
);
1422 /* If we do email verify, make sure we don't spam the address. */
1423 if ((hil
= dict_find(nickserv_email_dict
, email_addr
, NULL
))) {
1425 for (nn
=0; nn
<hil
->used
; nn
++) {
1426 if (hil
->list
[nn
]->cookie
) {
1427 reply("NSMSG_EMAIL_UNACTIVATED");
1431 if (hil
->used
>= nickserv_conf
.handles_per_email
) {
1432 reply("NSMSG_EMAIL_OVERUSED");
1445 /* Webregister hack - send URL instead of IRC cookie
1448 if((argc
>= 5) && !strcmp(argv
[4],"WEBLINK"))
1452 if (!(hi
= nickserv_register(user
, user
, argv
[1], password
, no_auth
)))
1454 /* Add any masks they should get. */
1455 if (nickserv_conf
.default_hostmask
) {
1456 string_list_append(hi
->masks
, strdup("*@*"));
1458 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
1459 if (irc_in_addr_is_valid(user
->ip
) && !irc_pton(&ip
, NULL
, user
->hostname
))
1460 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_BYIP
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
1463 /* If they're the first to register, give them level 1000. */
1464 if (dict_size(nickserv_handle_dict
) == 1) {
1465 hi
->opserv_level
= 1000;
1466 reply("NSMSG_ROOT_HANDLE", argv
[1]);
1469 /* Set their email address. */
1472 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1474 if((rc
= ldap_do_modify(hi
->handle
, NULL
, email_addr
)) != LDAP_SUCCESS
) {
1475 /* Falied to update email in ldap, but still
1476 * updated it here.. what should we do? */
1477 reply("NSMSG_LDAP_FAIL_EMAIL", ldap_err2string(rc
));
1479 nickserv_set_email_addr(hi
, email_addr
);
1483 nickserv_set_email_addr(hi
, email_addr
);
1486 nickserv_set_email_addr(hi
, email_addr
);
1490 /* If they need to do email verification, tell them. */
1492 nickserv_make_cookie(user
, hi
, ACTIVATION
, hi
->passwd
, weblink
);
1494 /* Set registering flag.. */
1495 user
->modes
|= FLAGS_REGISTERING
;
1497 if (nickserv_conf
.sync_log
) {
1498 cryptpass(password
, syncpass
);
1500 * An 0 is only sent if theres no email address. Thios should only happen if email functions are
1501 * disabled which they wont be for us. Email Required MUST be set on if you are using this.
1504 SyncLog("REGISTER %s %s %s %s", hi
->handle
, syncpass
, email_addr
? email_addr
: "0", user
->info
);
1507 /* this wont work if email is required .. */
1508 process_adduser_pending(user
);
1513 static NICKSERV_FUNC(cmd_oregister
)
1515 struct userNode
*settee
= NULL
;
1516 struct handle_info
*hi
;
1517 char* account
= NULL
;
1523 NICKSERV_MIN_PARMS(2);
1527 if(nickserv_conf
.force_handles_lowercase
)
1528 irc_strtolower(account
);
1529 if (!is_valid_handle(argv
[1])) {
1530 reply("NSMSG_BAD_HANDLE", argv
[1]);
1533 if (nickserv_conf
.email_required
) {
1534 NICKSERV_MIN_PARMS(3);
1536 if (argc
> 4) {/* take: "acct pass email mask nick" or "acct pass email mask" or "acct pass email nick" */
1537 if (strchr(argv
[4], '@'))
1547 if (argc
> 3) {/* take: "account pass mask nick" or "account pass mask" or "account pass nick" */
1548 if (strchr(argv
[3], '@'))
1557 /* If they passed a nick, look for that user.. */
1558 if (nick
&& !(settee
= GetUserH(nick
))) {
1559 reply("MSG_NICK_UNKNOWN", argv
[4]);
1562 /* If the setee is already authed, we cant add a 2nd account for them.. */
1563 if (settee
&& settee
->handle_info
) {
1564 reply("NSMSG_USER_PREV_AUTH", settee
->nick
);
1567 /* If there is no default mask in the conf, and they didn't pass a mask,
1568 * but we did find a user by nick, generate the mask */
1570 if (nickserv_conf
.default_hostmask
)
1573 mask
= generate_hostmask(settee
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
1575 reply("NSMSG_REGISTER_BAD_NICKMASK");
1580 if (!(hi
= nickserv_register(user
, settee
, account
, pass
, 0))) {
1581 return 0; /* error reply handled by above */
1585 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1587 if((rc
= ldap_do_modify(hi
->handle
, NULL
, email
)) != LDAP_SUCCESS
) {
1588 /* Falied to update email in ldap, but still
1589 * updated it here.. what should we do? */
1590 reply("NSMSG_LDAP_FAIL_EMAIL", ldap_err2string(rc
));
1592 nickserv_set_email_addr(hi
, email
);
1596 nickserv_set_email_addr(hi
, email
);
1599 nickserv_set_email_addr(hi
, email
);
1603 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
1604 if (mask_canonicalized
)
1605 string_list_append(hi
->masks
, mask_canonicalized
);
1608 if (nickserv_conf
.sync_log
)
1609 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, email
? email
: "@", user
->info
); /* Send just @ for email if none */
1614 nickserv_ignore(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, char *mask
)
1617 struct userNode
*target
;
1618 char *new_mask
= strdup(pretty_mask(mask
));
1619 for (i
=0; i
<hi
->ignores
->used
; i
++) {
1620 if (!irccasecmp(new_mask
, hi
->ignores
->list
[i
])) {
1621 reply("NSMSG_ADDIGNORE_ALREADY", new_mask
);
1626 string_list_append(hi
->ignores
, new_mask
);
1627 reply("NSMSG_ADDIGNORE_SUCCESS", new_mask
);
1629 for (target
= hi
->users
; target
; target
= target
->next_authed
) {
1630 irc_silence(target
, new_mask
, 1);
1635 static NICKSERV_FUNC(cmd_addignore
)
1637 NICKSERV_MIN_PARMS(2);
1639 return nickserv_ignore(cmd
, user
, user
->handle_info
, argv
[1]);
1642 static NICKSERV_FUNC(cmd_oaddignore
)
1644 struct handle_info
*hi
;
1646 NICKSERV_MIN_PARMS(3);
1647 if (!(hi
= get_victim_oper(user
, argv
[1])))
1650 return nickserv_ignore(cmd
, user
, hi
, argv
[2]);
1654 nickserv_delignore(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, char *del_mask
)
1657 struct userNode
*target
;
1658 char *pmask
= strdup(pretty_mask(del_mask
));
1659 for (i
=0; i
<hi
->ignores
->used
; i
++) {
1660 if (!strcmp(pmask
, hi
->ignores
->list
[i
]) || !strcmp(del_mask
, hi
->ignores
->list
[i
])) {
1661 char *old_mask
= hi
->ignores
->list
[i
];
1662 hi
->ignores
->list
[i
] = hi
->ignores
->list
[--hi
->ignores
->used
];
1663 reply("NSMSG_DELMASK_SUCCESS", old_mask
);
1664 for (target
= hi
->users
; target
; target
= target
->next_authed
) {
1665 irc_silence(target
, old_mask
, 0);
1672 reply("NSMSG_DELMASK_NOT_FOUND");
1676 static NICKSERV_FUNC(cmd_delignore
)
1678 NICKSERV_MIN_PARMS(2);
1679 return nickserv_delignore(cmd
, user
, user
->handle_info
, argv
[1]);
1682 static NICKSERV_FUNC(cmd_odelignore
)
1684 struct handle_info
*hi
;
1685 NICKSERV_MIN_PARMS(3);
1686 if (!(hi
= get_victim_oper(user
, argv
[1])))
1688 return nickserv_delignore(cmd
, user
, hi
, argv
[2]);
1691 static NICKSERV_FUNC(cmd_handleinfo
)
1694 unsigned int i
, pos
=0, herelen
;
1695 struct userNode
*target
, *next_un
;
1696 struct handle_info
*hi
;
1697 const char *nsmsg_none
;
1700 if (!(hi
= user
->handle_info
)) {
1701 reply("NSMSG_MUST_AUTH");
1704 } else if (!(hi
= modcmd_get_handle_info(user
, argv
[1]))) {
1708 nsmsg_none
= handle_find_message(hi
, "MSG_NONE");
1709 reply("NSMSG_HANDLEINFO_ON", hi
->handle
);
1711 reply("NSMSG_HANDLEINFO_REGGED", ctime(&hi
->registered
));
1714 intervalString(buff
, now
- hi
->lastseen
, user
->handle_info
);
1715 reply("NSMSG_HANDLEINFO_LASTSEEN", buff
);
1717 reply("NSMSG_HANDLEINFO_LASTSEEN_NOW");
1720 reply("NSMSG_HANDLEINFO_INFOLINE", (hi
->infoline
? hi
->infoline
: nsmsg_none
));
1721 if (HANDLE_FLAGGED(hi
, FROZEN
))
1722 reply("NSMSG_HANDLEINFO_VACATION");
1724 if (oper_has_access(user
, cmd
->parent
->bot
, 0, 1)) {
1725 struct do_not_register
*dnr
;
1726 if ((dnr
= chanserv_is_dnr(NULL
, hi
)))
1727 reply("NSMSG_HANDLEINFO_DNR", dnr
->setter
, dnr
->reason
);
1728 if ((user
->handle_info
->opserv_level
< 900) && !oper_outranks(user
, hi
))
1730 } else if (hi
!= user
->handle_info
) {
1731 reply("NSMSG_HANDLEINFO_END");
1736 reply("NSMSG_HANDLEINFO_KARMA", hi
->karma
);
1738 if (nickserv_conf
.email_enabled
)
1739 reply("NSMSG_HANDLEINFO_EMAIL_ADDR", visible_email_addr(user
, hi
));
1743 switch (hi
->cookie
->type
) {
1744 case ACTIVATION
: type
= "NSMSG_HANDLEINFO_COOKIE_ACTIVATION"; break;
1745 case PASSWORD_CHANGE
: type
= "NSMSG_HANDLEINFO_COOKIE_PASSWORD"; break;
1746 case EMAIL_CHANGE
: type
= "NSMSG_HANDLEINFO_COOKIE_EMAIL"; break;
1747 case ALLOWAUTH
: type
= "NSMSG_HANDLEINFO_COOKIE_ALLOWAUTH"; break;
1748 default: type
= "NSMSG_HANDLEINFO_COOKIE_UNKNOWN"; break;
1754 unsigned long flen
= 1;
1755 char flags
[34]; /* 32 bits possible plus '+' and '\0' */
1757 for (i
=0, flen
=1; handle_flags
[i
]; i
++)
1758 if (hi
->flags
& 1 << i
)
1759 flags
[flen
++] = handle_flags
[i
];
1761 reply("NSMSG_HANDLEINFO_FLAGS", flags
);
1763 reply("NSMSG_HANDLEINFO_FLAGS", nsmsg_none
);
1766 if (HANDLE_FLAGGED(hi
, SUPPORT_HELPER
)
1767 || HANDLE_FLAGGED(hi
, NETWORK_HELPER
)
1768 || (hi
->opserv_level
> 0)) {
1769 reply("NSMSG_HANDLEINFO_EPITHET", (hi
->epithet
? hi
->epithet
: nsmsg_none
));
1772 if (IsHelping(user
) || IsOper(user
))
1777 strftime(date
, 64, "%b %d %Y", localtime(&hi
->note
->date
));
1778 reply("NSMSG_HANDLEINFO_NOTE", hi
->note
->setter
, date
, hi
->note
->note
);
1783 reply("NSMSG_HANDLEINFO_FAKEHOST", (hi
->fakehost
? hi
->fakehost
: handle_find_message(hi
, "MSG_NONE")));
1785 if (hi
->last_quit_host
[0])
1786 reply("NSMSG_HANDLEINFO_LAST_HOST", hi
->last_quit_host
);
1788 reply("NSMSG_HANDLEINFO_LAST_HOST_UNKNOWN");
1790 if (nickserv_conf
.disable_nicks
) {
1791 /* nicks disabled; don't show anything about registered nicks */
1792 } else if (hi
->nicks
) {
1793 struct nick_info
*ni
, *next_ni
;
1794 for (ni
= hi
->nicks
; ni
; ni
= next_ni
) {
1795 herelen
= strlen(ni
->nick
);
1796 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1798 goto print_nicks_buff
;
1802 memcpy(buff
+pos
, ni
->nick
, herelen
);
1803 pos
+= herelen
; buff
[pos
++] = ' ';
1807 reply("NSMSG_HANDLEINFO_NICKS", buff
);
1812 reply("NSMSG_HANDLEINFO_NICKS", nsmsg_none
);
1815 if (hi
->masks
->used
) {
1816 for (i
=0; i
< hi
->masks
->used
; i
++) {
1817 herelen
= strlen(hi
->masks
->list
[i
]);
1818 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1820 goto print_mask_buff
;
1822 memcpy(buff
+pos
, hi
->masks
->list
[i
], herelen
);
1823 pos
+= herelen
; buff
[pos
++] = ' ';
1824 if (i
+1 == hi
->masks
->used
) {
1827 reply("NSMSG_HANDLEINFO_MASKS", buff
);
1832 reply("NSMSG_HANDLEINFO_MASKS", nsmsg_none
);
1835 if (hi
->sslfps
->used
) {
1836 for (i
=0; i
< hi
->sslfps
->used
; i
++) {
1837 herelen
= strlen(hi
->sslfps
->list
[i
]);
1838 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1840 goto print_sslfp_buff
;
1842 memcpy(buff
+pos
, hi
->sslfps
->list
[i
], herelen
);
1843 pos
+= herelen
; buff
[pos
++] = ' ';
1844 if (i
+1 == hi
->sslfps
->used
) {
1847 reply("NSMSG_HANDLEINFO_SSLFPS", buff
);
1852 reply("NSMSG_HANDLEINFO_SSLFPS", nsmsg_none
);
1855 if (hi
->ignores
->used
) {
1856 for (i
=0; i
< hi
->ignores
->used
; i
++) {
1857 herelen
= strlen(hi
->ignores
->list
[i
]);
1858 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1860 goto print_ignore_buff
;
1862 memcpy(buff
+pos
, hi
->ignores
->list
[i
], herelen
);
1863 pos
+= herelen
; buff
[pos
++] = ' ';
1864 if (i
+1 == hi
->ignores
->used
) {
1867 reply("NSMSG_HANDLEINFO_IGNORES", buff
);
1872 reply("NSMSG_HANDLEINFO_IGNORES", nsmsg_none
);
1876 struct userData
*chan
, *next
;
1879 for (chan
= hi
->channels
; chan
; chan
= next
) {
1880 next
= chan
->u_next
;
1881 name
= chan
->channel
->channel
->name
;
1882 herelen
= strlen(name
);
1883 if (pos
+ herelen
+ 7 > ArrayLength(buff
)) {
1885 goto print_chans_buff
;
1887 if (IsUserSuspended(chan
))
1889 pos
+= sprintf(buff
+pos
, "%s:%s ", user_level_name_from_level(chan
->access
), name
);
1893 reply("NSMSG_HANDLEINFO_CHANNELS", buff
);
1898 reply("NSMSG_HANDLEINFO_CHANNELS", nsmsg_none
);
1901 for (target
= hi
->users
; target
; target
= next_un
) {
1902 herelen
= strlen(target
->nick
);
1903 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1905 goto print_cnick_buff
;
1907 next_un
= target
->next_authed
;
1909 memcpy(buff
+pos
, target
->nick
, herelen
);
1910 pos
+= herelen
; buff
[pos
++] = ' ';
1914 reply("NSMSG_HANDLEINFO_CURRENT", buff
);
1919 reply("NSMSG_HANDLEINFO_END");
1920 return 1 | ((hi
!= user
->handle_info
) ? CMD_LOG_STAFF
: 0);
1923 static NICKSERV_FUNC(cmd_userinfo
)
1925 struct userNode
*target
;
1927 NICKSERV_MIN_PARMS(2);
1928 if (!(target
= GetUserH(argv
[1]))) {
1929 reply("MSG_NICK_UNKNOWN", argv
[1]);
1932 if (target
->handle_info
)
1933 reply("NSMSG_USERINFO_AUTHED_AS", target
->nick
, target
->handle_info
->handle
);
1935 reply("NSMSG_USERINFO_NOT_AUTHED", target
->nick
);
1939 static NICKSERV_FUNC(cmd_nickinfo
)
1941 struct nick_info
*ni
;
1943 NICKSERV_MIN_PARMS(2);
1944 if (!(ni
= get_nick_info(argv
[1]))) {
1945 reply("MSG_NICK_UNKNOWN", argv
[1]);
1948 reply("NSMSG_NICKINFO_OWNER", ni
->nick
, ni
->owner
->handle
);
1952 static NICKSERV_FUNC(cmd_rename_handle
)
1954 struct handle_info
*hi
;
1955 struct userNode
*uNode
;
1959 NICKSERV_MIN_PARMS(3);
1960 if(nickserv_conf
.force_handles_lowercase
)
1961 irc_strtolower(argv
[2]);
1962 if (!(hi
= get_victim_oper(user
, argv
[1])))
1964 if (!is_valid_handle(argv
[2])) {
1965 reply("NSMSG_FAIL_RENAME", argv
[1], argv
[2]);
1968 if (get_handle_info(argv
[2])) {
1969 reply("NSMSG_HANDLE_EXISTS", argv
[2]);
1972 if(strlen(argv
[2]) > 30)
1974 reply("NMSG_HANDLE_TOLONG", argv
[2], 30);
1978 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1980 if( (rc
= ldap_rename_account(hi
->handle
, argv
[2])) != LDAP_SUCCESS
) {
1981 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
1987 dict_remove2(nickserv_handle_dict
, old_handle
= hi
->handle
, 1);
1988 hi
->handle
= strdup(argv
[2]);
1989 dict_insert(nickserv_handle_dict
, hi
->handle
, hi
);
1990 for (nn
=0; nn
<rf_list_used
; nn
++)
1991 rf_list
[nn
](hi
, old_handle
, rf_list_extra
[nn
]);
1993 if (nickserv_conf
.sync_log
) {
1994 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
1995 irc_rename(uNode
, hi
->handle
);
1997 SyncLog("RENAME %s %s", old_handle
, hi
->handle
);
2000 reply("NSMSG_HANDLE_CHANGED", old_handle
, hi
->handle
);
2001 global_message_args(MESSAGE_RECIPIENT_OPERS
, "NSMSG_ACCOUNT_RENAMED",
2002 user
->handle_info
->handle
, old_handle
, hi
->handle
);
2008 static failpw_func_t
*failpw_func_list
;
2009 static void **failpw_func_list_extra
;
2010 static unsigned int failpw_func_size
= 0, failpw_func_used
= 0;
2013 reg_failpw_func(failpw_func_t func
, void *extra
)
2015 if (failpw_func_used
== failpw_func_size
) {
2016 if (failpw_func_size
) {
2017 failpw_func_size
<<= 1;
2018 failpw_func_list
= realloc(failpw_func_list
, failpw_func_size
*sizeof(failpw_func_t
));
2019 failpw_func_list_extra
= realloc(failpw_func_list_extra
, failpw_func_size
*sizeof(void*));
2021 failpw_func_size
= 8;
2022 failpw_func_list
= malloc(failpw_func_size
*sizeof(failpw_func_t
));
2023 failpw_func_list_extra
= malloc(failpw_func_size
*sizeof(void*));
2026 failpw_func_list
[failpw_func_used
] = func
;
2027 failpw_func_list_extra
[failpw_func_used
++] = extra
;
2031 * Return hi if the handle/pass pair matches, NULL if it doesnt.
2033 * called by nefariouses enhanced AC login-on-connect code
2036 struct handle_info
*loc_auth(char *sslfp
, char *handle
, char *password
, char *userhost
)
2038 int wildmask
= 0, auth
= 0;
2039 int used
, maxlogins
;
2041 struct handle_info
*hi
;
2042 struct userNode
*other
;
2044 int ldap_result
= LDAP_SUCCESS
;
2048 hi
= dict_find(nickserv_handle_dict
, handle
, NULL
);
2051 if (nickserv_conf
.ldap_enable
) {
2052 ldap_result
= ldap_check_auth(handle
, password
);
2053 if (!hi
&& (ldap_result
!= LDAP_SUCCESS
))
2055 if (ldap_result
== LDAP_SUCCESS
) {
2056 /* Mark auth as successful */
2060 if (!hi
&& (ldap_result
== LDAP_SUCCESS
) && nickserv_conf
.ldap_autocreate
) {
2061 /* user not found, but authed to ldap successfully..
2062 * create the account.
2067 /* Add a *@* mask */
2068 /* TODO if userhost is not null, build mask based on that. */
2069 if(nickserv_conf
.default_hostmask
)
2072 return NULL
; /* They dont have a *@* mask so they can't loc */
2074 if(!(hi
= nickserv_register(NULL
, NULL
, handle
, password
, 0))) {
2075 return 0; /* couldn't add the user for some reason */
2078 if((rc
= ldap_get_user_info(handle
, &email
) != LDAP_SUCCESS
))
2080 if(nickserv_conf
.email_required
) {
2085 nickserv_set_email_addr(hi
, email
);
2089 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
2090 string_list_append(hi
->masks
, mask_canonicalized
);
2092 if(nickserv_conf
.sync_log
)
2093 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, "@", handle
);
2098 /* hi should now be a valid handle, if not return NULL */
2103 if (password
&& *password
&& !nickserv_conf
.ldap_enable
) {
2105 if (password
&& *password
) {
2107 if (checkpass(password
, hi
->passwd
))
2111 if (!auth
&& sslfp
&& *sslfp
&& hi
->sslfps
->used
) {
2112 /* If any SSL fingerprint matches, allow it. */
2113 for (ii
=0; ii
<hi
->sslfps
->used
; ii
++) {
2114 if (!irccasecmp(sslfp
, hi
->sslfps
->list
[ii
])) {
2121 /* Auth should have succeeded by this point */
2125 /* We don't know the users hostname, or anything because they
2126 * havn't registered yet. So we can only allow LOC if your
2127 * account has *@* as a hostmask.
2129 * UPDATE: New nefarious LOC supports u@h
2139 buf
= strdup(userhost
);
2140 ident
= mysep(&buf
, "@");
2141 realhost
= mysep(&buf
, ":");
2142 ip
= mysep(&buf
, ":");
2143 if(!ip
|| !realhost
|| !ident
) {
2145 return NULL
; /* Invalid AC request, just quit */
2147 uh
= malloc(strlen(userhost
));
2148 ui
= malloc(strlen(userhost
));
2149 sprintf(uh
, "%s@%s", ident
, realhost
);
2150 sprintf(ui
, "%s@%s", ident
, ip
);
2151 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
2153 if(match_ircglob(uh
, hi
->masks
->list
[ii
])
2154 || match_ircglob(ui
, hi
->masks
->list
[ii
]))
2166 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
2168 if (!strcmp(hi
->masks
->list
[ii
], "*@*"))
2178 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2182 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
2183 for (used
= 0, other
= hi
->users
; other
; other
= other
->next_authed
) {
2184 if (++used
>= maxlogins
) {
2188 /* TODO - Add LOGGING to this function so LOC's are logged.. */
2192 static NICKSERV_FUNC(cmd_auth
)
2194 char *privv
[MAXNUMPARAMS
];
2196 int pw_arg
, used
, maxlogins
;
2197 struct handle_info
*hi
;
2200 struct userNode
*other
;
2202 int ldap_result
= LDAP_OTHER
;
2206 if (user
->handle_info
) {
2207 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2210 if (IsStamped(user
)) {
2211 /* Unauthenticated users might still have been stamped
2212 previously and could therefore have a hidden host;
2213 do not allow them to authenticate. */
2214 reply("NSMSG_STAMPED_AUTH");
2221 hi
= dict_find(nickserv_handle_dict
, argv
[1], NULL
);
2222 } else if (argc
== 2) {
2225 if (nickserv_conf
.disable_nicks
) {
2226 hi
= get_handle_info(user
->nick
);
2228 /* try to look up their handle from their nick */
2229 /* TODO: handle ldap auth on nickserv style networks, too */
2230 struct nick_info
*ni
;
2231 ni
= get_nick_info(user
->nick
);
2233 reply("NSMSG_NICK_NOT_REGISTERED", user
->nick
);
2239 handle
= hi
->handle
;
2241 handle
= user
->nick
;
2244 reply("MSG_MISSING_PARAMS", argv
[0]);
2245 svccmd_send_help_brief(user
, nickserv
, cmd
);
2250 if(strchr(argv
[1], '<') || strchr(handle
, '>')) {
2251 reply("NSMSG_NO_ANGLEBRACKETS");
2254 if (!is_valid_handle(handle
)) {
2255 reply("NSMSG_BAD_HANDLE", handle
);
2259 if(nickserv_conf
.ldap_enable
) {
2260 ldap_result
= ldap_check_auth(handle
, passwd
);
2261 /* Get the users email address and update it */
2262 if(ldap_result
== LDAP_SUCCESS
) {
2264 if((rc
= ldap_get_user_info(handle
, &email
) != LDAP_SUCCESS
))
2266 if(nickserv_conf
.email_required
) {
2267 reply("NSMSG_LDAP_FAIL_GET_EMAIL", ldap_err2string(rc
));
2272 else if(ldap_result
!= LDAP_INVALID_CREDENTIALS
) {
2273 reply("NSMSG_LDAP_FAIL", ldap_err2string(ldap_result
));
2281 if(nickserv_conf
.ldap_enable
&& ldap_result
== LDAP_SUCCESS
&& nickserv_conf
.ldap_autocreate
) {
2282 /* user not found, but authed to ldap successfully..
2283 * create the account.
2286 if(!(hi
= nickserv_register(user
, NULL
, argv
[1], argv
[2], 0))) {
2287 reply("NSMSG_UNABLE_TO_ADD");
2288 return 0; /* couldn't add the user for some reason */
2290 /* Add a *@* mask */
2291 if(nickserv_conf
.default_hostmask
)
2294 mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2297 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
2298 string_list_append(hi
->masks
, mask_canonicalized
);
2301 nickserv_set_email_addr(hi
, email
);
2304 if(nickserv_conf
.sync_log
)
2305 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, email
? email
: "@", user
->info
);
2309 reply("NSMSG_HANDLE_NOT_FOUND");
2315 /* Responses from here on look up the language used by the handle they asked about. */
2316 if (!valid_user_for(user
, hi
)) {
2317 if (hi
->email_addr
&& nickserv_conf
.email_enabled
)
2318 send_message_type(4, user
, cmd
->parent
->bot
,
2319 handle_find_message(hi
, "NSMSG_USE_AUTHCOOKIE"),
2322 send_message_type(4, user
, cmd
->parent
->bot
,
2323 handle_find_message(hi
, "NSMSG_HOSTMASK_INVALID"),
2325 argv
[pw_arg
] = "BADMASK";
2329 if(( ( nickserv_conf
.ldap_enable
&& ldap_result
== LDAP_INVALID_CREDENTIALS
) ||
2330 ( (!nickserv_conf
.ldap_enable
) && (!checkpass(passwd
, hi
->passwd
)) ) ) && !valid_user_sslfp(user
, hi
)) {
2332 if (!checkpass(passwd
, hi
->passwd
) && !valid_user_sslfp(user
, hi
)) {
2335 send_message_type(4, user
, cmd
->parent
->bot
,
2336 handle_find_message(hi
, "NSMSG_PASSWORD_INVALID"));
2337 argv
[pw_arg
] = "BADPASS";
2338 for (n
=0; n
<failpw_func_used
; n
++)
2339 failpw_func_list
[n
](user
, hi
, failpw_func_list_extra
[n
]);
2340 if (nickserv_conf
.autogag_enabled
) {
2341 if (!user
->auth_policer
.params
) {
2342 user
->auth_policer
.last_req
= now
;
2343 user
->auth_policer
.params
= nickserv_conf
.auth_policer_params
;
2345 if (!policer_conforms(&user
->auth_policer
, now
, 1.0)) {
2347 hostmask
= generate_hostmask(user
, GENMASK_STRICT_HOST
|GENMASK_BYIP
|GENMASK_NO_HIDING
);
2348 log_module(NS_LOG
, LOG_INFO
, "%s auto-gagged for repeated password guessing.", hostmask
);
2349 gag_create(hostmask
, nickserv
->nick
, "Repeated password guessing.", now
+nickserv_conf
.autogag_duration
);
2351 argv
[pw_arg
] = "GAGGED";
2356 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2357 send_message_type(4, user
, cmd
->parent
->bot
,
2358 handle_find_message(hi
, "NSMSG_HANDLE_SUSPENDED"));
2359 argv
[pw_arg
] = "SUSPENDED";
2362 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
2363 for (used
= 0, other
= hi
->users
; other
; other
= other
->next_authed
) {
2364 if (++used
>= maxlogins
) {
2365 send_message_type(4, user
, cmd
->parent
->bot
,
2366 handle_find_message(hi
, "NSMSG_MAX_LOGINS"),
2368 argv
[pw_arg
] = "MAXLOGINS";
2373 set_user_handle_info(user
, hi
, 1);
2374 if (nickserv_conf
.email_required
&& !hi
->email_addr
)
2375 reply("NSMSG_PLEASE_SET_EMAIL");
2376 if (!is_secure_password(hi
->handle
, passwd
, NULL
))
2377 reply("NSMSG_WEAK_PASSWORD");
2378 if (hi
->passwd
[0] != '$')
2379 cryptpass(passwd
, hi
->passwd
);
2381 /* If a channel was waiting for this user to auth,
2382 * finish adding them */
2383 process_adduser_pending(user
);
2385 reply("NSMSG_AUTH_SUCCESS");
2388 /* Set +x if autohide is on */
2389 if(HANDLE_FLAGGED(hi
, AUTOHIDE
))
2390 irc_umode(user
, "+x");
2392 if(!IsOper(user
)) /* If they arnt already opered.. */
2394 /* Auto Oper users with Opserv access -Life4Christ 8-10-2005 */
2395 if( nickserv_conf
.auto_admin
[0] && hi
->opserv_level
>= opserv_conf_admin_level())
2397 if (nickserv_conf
.auto_admin_privs
[0]) {
2398 irc_raw_privs(user
, nickserv_conf
.auto_admin_privs
);
2399 privc
= split_line(strdup(nickserv_conf
.auto_admin_privs
), false, MAXNUMPARAMS
, privv
);
2400 for (i
= 0; i
< privc
; i
++) {
2401 client_modify_priv_by_name(user
, privv
[i
], 1);
2404 irc_umode(user
,nickserv_conf
.auto_admin
);
2405 reply("NSMSG_AUTO_OPER_ADMIN");
2407 else if (nickserv_conf
.auto_oper
[0] && hi
->opserv_level
> 0)
2409 if (nickserv_conf
.auto_oper_privs
[0]) {
2410 irc_raw_privs(user
, nickserv_conf
.auto_oper_privs
);
2411 privc
= split_line(strdup(nickserv_conf
.auto_oper_privs
), false, MAXNUMPARAMS
, privv
);
2412 for (i
= 0; i
< privc
; i
++) {
2413 client_modify_priv_by_name(user
, privv
[i
], 1);
2416 irc_umode(user
,nickserv_conf
.auto_oper
);
2417 reply("NSMSG_AUTO_OPER");
2421 /* Wipe out the pass for the logs */
2423 if (!hi
->masks
->used
) {
2425 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
2426 if (irc_in_addr_is_valid(user
->ip
) && irc_pton(&ip
, NULL
, user
->hostname
))
2427 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_BYIP
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
2430 argv
[pw_arg
] = "****";
2434 static allowauth_func_t
*allowauth_func_list
;
2435 static void **allowauth_func_list_extra
;
2436 static unsigned int allowauth_func_size
= 0, allowauth_func_used
= 0;
2439 reg_allowauth_func(allowauth_func_t func
, void *extra
)
2441 if (allowauth_func_used
== allowauth_func_size
) {
2442 if (allowauth_func_size
) {
2443 allowauth_func_size
<<= 1;
2444 allowauth_func_list
= realloc(allowauth_func_list
, allowauth_func_size
*sizeof(allowauth_func_t
));
2445 allowauth_func_list_extra
= realloc(allowauth_func_list_extra
, allowauth_func_size
*sizeof(void*));
2447 allowauth_func_size
= 8;
2448 allowauth_func_list
= malloc(allowauth_func_size
*sizeof(allowauth_func_t
));
2449 allowauth_func_list_extra
= malloc(allowauth_func_size
*sizeof(void*));
2452 allowauth_func_list
[allowauth_func_used
] = func
;
2453 allowauth_func_list_extra
[allowauth_func_used
++] = extra
;
2456 static NICKSERV_FUNC(cmd_allowauth
)
2458 struct userNode
*target
;
2459 struct handle_info
*hi
;
2462 NICKSERV_MIN_PARMS(2);
2463 if (!(target
= GetUserH(argv
[1]))) {
2464 reply("MSG_NICK_UNKNOWN", argv
[1]);
2467 if (target
->handle_info
) {
2468 reply("NSMSG_USER_PREV_AUTH", target
->nick
);
2471 if (IsStamped(target
)) {
2472 /* Unauthenticated users might still have been stamped
2473 previously and could therefore have a hidden host;
2474 do not allow them to authenticate to an account. */
2475 reply("NSMSG_USER_PREV_STAMP", target
->nick
);
2480 else if (!(hi
= get_handle_info(argv
[2]))) {
2481 reply("MSG_HANDLE_UNKNOWN", argv
[2]);
2485 if (hi
->opserv_level
> user
->handle_info
->opserv_level
) {
2486 reply("MSG_USER_OUTRANKED", hi
->handle
);
2489 if (((hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
))
2490 || (hi
->opserv_level
> 0))
2491 && ((argc
< 4) || irccasecmp(argv
[3], "staff"))) {
2492 reply("NSMSG_ALLOWAUTH_STAFF", hi
->handle
);
2495 dict_insert(nickserv_allow_auth_dict
, target
->nick
, hi
);
2496 reply("NSMSG_AUTH_ALLOWED", target
->nick
, hi
->handle
);
2497 send_message(target
, nickserv
, "NSMSG_AUTH_ALLOWED_MSG", hi
->handle
, hi
->handle
);
2498 if (nickserv_conf
.email_enabled
)
2499 send_message(target
, nickserv
, "NSMSG_AUTH_ALLOWED_EMAIL");
2501 if (dict_remove(nickserv_allow_auth_dict
, target
->nick
))
2502 reply("NSMSG_AUTH_NORMAL_ONLY", target
->nick
);
2504 reply("NSMSG_AUTH_UNSPECIAL", target
->nick
);
2506 for (n
=0; n
<allowauth_func_used
; n
++)
2507 allowauth_func_list
[n
](user
, target
, hi
, allowauth_func_list_extra
[n
]);
2511 static NICKSERV_FUNC(cmd_authcookie
)
2513 struct handle_info
*hi
;
2515 NICKSERV_MIN_PARMS(2);
2516 if (user
->handle_info
) {
2517 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2520 if (IsStamped(user
)) {
2521 /* Unauthenticated users might still have been stamped
2522 previously and could therefore have a hidden host;
2523 do not allow them to authenticate to an account. */
2524 reply("NSMSG_STAMPED_AUTHCOOKIE");
2527 if (!(hi
= get_handle_info(argv
[1]))) {
2528 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2531 if (!hi
->email_addr
) {
2532 reply("MSG_SET_EMAIL_ADDR");
2535 nickserv_make_cookie(user
, hi
, ALLOWAUTH
, NULL
, 0);
2539 static NICKSERV_FUNC(cmd_delcookie
)
2541 struct handle_info
*hi
;
2543 hi
= user
->handle_info
;
2545 reply("NSMSG_NO_COOKIE");
2548 switch (hi
->cookie
->type
) {
2551 reply("NSMSG_MUST_TIME_OUT");
2554 nickserv_eat_cookie(hi
->cookie
);
2555 reply("NSMSG_ATE_COOKIE");
2561 static NICKSERV_FUNC(cmd_odelcookie
)
2563 struct handle_info
*hi
;
2565 NICKSERV_MIN_PARMS(2);
2567 if (!(hi
= get_victim_oper(user
, argv
[1])))
2571 reply("NSMSG_NO_COOKIE_FOREIGN", hi
->handle
);
2575 switch (hi
->cookie
->type
) {
2577 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2579 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2581 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2582 /* Falied to update password in ldap, but still
2583 * updated it here.. what should we do? */
2584 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2589 if (nickserv_conf
.sync_log
)
2590 SyncLog("ACCOUNTACC %s", hi
->handle
);
2592 case PASSWORD_CHANGE
:
2599 reply("NSMSG_BAD_COOKIE_TYPE", hi
->cookie
->type
);
2600 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d for account %s.", hi
->cookie
->type
, hi
->handle
);
2604 nickserv_eat_cookie(hi
->cookie
);
2605 reply("NSMSG_ATE_FOREIGN_COOKIE", hi
->handle
);
2610 static NICKSERV_FUNC(cmd_resetpass
)
2612 struct handle_info
*hi
;
2613 char crypted
[MD5_CRYPT_LENGTH
];
2616 NICKSERV_MIN_PARMS(3);
2617 if(argc
>= 4 && !strcmp(argv
[3], "WEBLINK"))
2621 if (user
->handle_info
) {
2622 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2625 if (IsStamped(user
)) {
2626 /* Unauthenticated users might still have been stamped
2627 previously and could therefore have a hidden host;
2628 do not allow them to activate an account. */
2629 reply("NSMSG_STAMPED_RESETPASS");
2632 if (!(hi
= get_handle_info(argv
[1]))) {
2633 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2636 if (!hi
->email_addr
) {
2637 reply("MSG_SET_EMAIL_ADDR");
2640 cryptpass(argv
[2], crypted
);
2642 nickserv_make_cookie(user
, hi
, PASSWORD_CHANGE
, crypted
, weblink
);
2646 static NICKSERV_FUNC(cmd_cookie
)
2648 struct handle_info
*hi
;
2651 if ((argc
== 2) && (hi
= user
->handle_info
) && hi
->cookie
&& (hi
->cookie
->type
== EMAIL_CHANGE
)) {
2654 NICKSERV_MIN_PARMS(3);
2655 if (!(hi
= get_handle_info(argv
[1]))) {
2656 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2662 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2663 reply("NSMSG_HANDLE_SUSPENDED");
2668 reply("NSMSG_NO_COOKIE");
2672 /* Check validity of operation before comparing cookie to
2673 * prohibit guessing by authed users. */
2674 if (user
->handle_info
2675 && (hi
->cookie
->type
!= EMAIL_CHANGE
)
2676 && (hi
->cookie
->type
!= PASSWORD_CHANGE
)) {
2677 reply("NSMSG_CANNOT_COOKIE");
2681 if (strcmp(cookie
, hi
->cookie
->cookie
)) {
2682 reply("NSMSG_BAD_COOKIE");
2686 switch (hi
->cookie
->type
) {
2689 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2691 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2692 /* Falied to update email in ldap, but still
2693 * updated it here.. what should we do? */
2694 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2699 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2700 set_user_handle_info(user
, hi
, 1);
2701 reply("NSMSG_HANDLE_ACTIVATED");
2702 if (nickserv_conf
.sync_log
)
2703 SyncLog("ACCOUNTACC %s", hi
->handle
);
2705 case PASSWORD_CHANGE
:
2707 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2709 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2710 /* Falied to update email in ldap, but still
2711 * updated it here.. what should we do? */
2712 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2717 set_user_handle_info(user
, hi
, 1);
2718 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2719 reply("NSMSG_PASSWORD_CHANGED");
2720 if (nickserv_conf
.sync_log
)
2721 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
2725 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2727 if((rc
= ldap_do_modify(hi
->handle
, NULL
, hi
->cookie
->data
)) != LDAP_SUCCESS
) {
2728 /* Falied to update email in ldap, but still
2729 * updated it here.. what should we do? */
2730 reply("NSMSG_LDAP_FAIL_SEND_EMAIL", ldap_err2string(rc
));
2735 if (!hi
->email_addr
&& nickserv_conf
.sync_log
) {
2737 * This should only happen if an OREGISTER was sent. Require
2738 * email must be enabled! - SiRVulcaN
2740 if (nickserv_conf
.sync_log
)
2741 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, hi
->cookie
->data
, user
->info
);
2744 nickserv_set_email_addr(hi
, hi
->cookie
->data
);
2745 reply("NSMSG_EMAIL_CHANGED");
2746 if (nickserv_conf
.sync_log
)
2747 SyncLog("EMAILCHANGE %s %s", hi
->handle
, hi
->cookie
->data
);
2750 char *mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2751 set_user_handle_info(user
, hi
, 1);
2752 nickserv_addmask(user
, hi
, mask
);
2753 reply("NSMSG_AUTH_SUCCESS");
2758 reply("NSMSG_BAD_COOKIE_TYPE", hi
->cookie
->type
);
2759 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d for account %s.", hi
->cookie
->type
, hi
->handle
);
2763 nickserv_eat_cookie(hi
->cookie
);
2765 process_adduser_pending(user
);
2770 static NICKSERV_FUNC(cmd_oregnick
) {
2772 struct handle_info
*target
;
2773 struct nick_info
*ni
;
2775 NICKSERV_MIN_PARMS(3);
2776 if (!(target
= modcmd_get_handle_info(user
, argv
[1])))
2779 if (!is_registerable_nick(nick
)) {
2780 reply("NSMSG_BAD_NICK", nick
);
2783 ni
= dict_find(nickserv_nick_dict
, nick
, NULL
);
2785 reply("NSMSG_NICK_EXISTS", nick
);
2788 register_nick(nick
, target
);
2789 reply("NSMSG_OREGNICK_SUCCESS", nick
, target
->handle
);
2793 static NICKSERV_FUNC(cmd_regnick
) {
2795 struct nick_info
*ni
;
2797 if (!is_registerable_nick(user
->nick
)) {
2798 reply("NSMSG_BAD_NICK", user
->nick
);
2801 /* count their nicks, see if it's too many */
2802 for (n
=0,ni
=user
->handle_info
->nicks
; ni
; n
++,ni
=ni
->next
) ;
2803 if (n
>= nickserv_conf
.nicks_per_handle
) {
2804 reply("NSMSG_TOO_MANY_NICKS");
2807 ni
= dict_find(nickserv_nick_dict
, user
->nick
, NULL
);
2809 reply("NSMSG_NICK_EXISTS", user
->nick
);
2812 register_nick(user
->nick
, user
->handle_info
);
2813 reply("NSMSG_REGNICK_SUCCESS", user
->nick
);
2817 static NICKSERV_FUNC(cmd_pass
)
2819 struct handle_info
*hi
;
2820 char *old_pass
, *new_pass
;
2821 char crypted
[MD5_CRYPT_LENGTH
+1];
2826 NICKSERV_MIN_PARMS(3);
2827 hi
= user
->handle_info
;
2831 if (!is_secure_password(hi
->handle
, new_pass
, user
)) return 0;
2834 if(nickserv_conf
.ldap_enable
) {
2835 ldap_result
= ldap_check_auth(hi
->handle
, old_pass
);
2836 if(ldap_result
!= LDAP_SUCCESS
) {
2837 if(ldap_result
== LDAP_INVALID_CREDENTIALS
)
2838 reply("NSMSG_PASSWORD_INVALID");
2840 reply("NSMSG_LDAP_FAIL", ldap_err2string(ldap_result
));
2845 if (!checkpass(old_pass
, hi
->passwd
)) {
2846 argv
[1] = "BADPASS";
2847 reply("NSMSG_PASSWORD_INVALID");
2850 cryptpass(new_pass
, crypted
);
2852 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2854 if((rc
= ldap_do_modify(hi
->handle
, crypted
, NULL
)) != LDAP_SUCCESS
) {
2855 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2860 //cryptpass(new_pass, hi->passwd);
2861 strcpy(hi
->passwd
, crypted
);
2862 if (nickserv_conf
.sync_log
)
2863 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
2865 reply("NSMSG_PASS_SUCCESS");
2870 nickserv_addmask(struct userNode
*user
, struct handle_info
*hi
, const char *mask
)
2873 char *new_mask
= canonicalize_hostmask(strdup(mask
));
2874 for (i
=0; i
<hi
->masks
->used
; i
++) {
2875 if (!irccasecmp(new_mask
, hi
->masks
->list
[i
])) {
2876 send_message(user
, nickserv
, "NSMSG_ADDMASK_ALREADY", new_mask
);
2881 string_list_append(hi
->masks
, new_mask
);
2882 send_message(user
, nickserv
, "NSMSG_ADDMASK_SUCCESS", new_mask
);
2886 static NICKSERV_FUNC(cmd_addmask
)
2889 char *mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2890 int res
= nickserv_addmask(user
, user
->handle_info
, mask
);
2894 if (!is_gline(argv
[1])) {
2895 reply("NSMSG_MASK_INVALID", argv
[1]);
2898 return nickserv_addmask(user
, user
->handle_info
, argv
[1]);
2902 static NICKSERV_FUNC(cmd_oaddmask
)
2904 struct handle_info
*hi
;
2906 NICKSERV_MIN_PARMS(3);
2907 if (!(hi
= get_victim_oper(user
, argv
[1])))
2909 return nickserv_addmask(user
, hi
, argv
[2]);
2913 nickserv_delmask(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, const char *del_mask
, int force
)
2916 for (i
=0; i
<hi
->masks
->used
; i
++) {
2917 if (!strcmp(del_mask
, hi
->masks
->list
[i
])) {
2918 char *old_mask
= hi
->masks
->list
[i
];
2919 if (hi
->masks
->used
== 1 && !force
) {
2920 reply("NSMSG_DELMASK_NOTLAST");
2923 hi
->masks
->list
[i
] = hi
->masks
->list
[--hi
->masks
->used
];
2924 reply("NSMSG_DELMASK_SUCCESS", old_mask
);
2929 reply("NSMSG_DELMASK_NOT_FOUND");
2933 static NICKSERV_FUNC(cmd_delmask
)
2935 NICKSERV_MIN_PARMS(2);
2936 return nickserv_delmask(cmd
, user
, user
->handle_info
, argv
[1], 0);
2939 static NICKSERV_FUNC(cmd_odelmask
)
2941 struct handle_info
*hi
;
2942 NICKSERV_MIN_PARMS(3);
2943 if (!(hi
= get_victim_oper(user
, argv
[1])))
2945 return nickserv_delmask(cmd
, user
, hi
, argv
[2], 1);
2949 nickserv_addsslfp(struct userNode
*user
, struct handle_info
*hi
, const char *sslfp
)
2952 char *new_sslfp
= strdup(sslfp
);
2953 for (i
=0; i
<hi
->sslfps
->used
; i
++) {
2954 if (!irccasecmp(new_sslfp
, hi
->sslfps
->list
[i
])) {
2955 send_message(user
, nickserv
, "NSMSG_ADDSSLFP_ALREADY", new_sslfp
);
2960 string_list_append(hi
->sslfps
, new_sslfp
);
2961 send_message(user
, nickserv
, "NSMSG_ADDSSLFP_SUCCESS", new_sslfp
);
2965 static NICKSERV_FUNC(cmd_addsslfp
)
2967 NICKSERV_MIN_PARMS((user
->sslfp
? 1 : 2));
2968 if ((argc
< 2) && (user
->sslfp
)) {
2969 int res
= nickserv_addsslfp(user
, user
->handle_info
, user
->sslfp
);
2972 return nickserv_addsslfp(user
, user
->handle_info
, argv
[1]);
2976 static NICKSERV_FUNC(cmd_oaddsslfp
)
2978 struct handle_info
*hi
;
2980 NICKSERV_MIN_PARMS(3);
2981 if (!(hi
= get_victim_oper(user
, argv
[1])))
2983 return nickserv_addsslfp(user
, hi
, argv
[2]);
2987 nickserv_delsslfp(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, const char *del_sslfp
)
2990 for (i
=0; i
<hi
->sslfps
->used
; i
++) {
2991 if (!irccasecmp(del_sslfp
, hi
->sslfps
->list
[i
])) {
2992 char *old_sslfp
= hi
->sslfps
->list
[i
];
2993 hi
->sslfps
->list
[i
] = hi
->sslfps
->list
[--hi
->sslfps
->used
];
2994 reply("NSMSG_DELSSLFP_SUCCESS", old_sslfp
);
2999 reply("NSMSG_DELSSLFP_NOT_FOUND");
3003 static NICKSERV_FUNC(cmd_delsslfp
)
3005 NICKSERV_MIN_PARMS((user
->sslfp
? 1 : 2));
3006 if ((argc
< 2) && (user
->sslfp
)) {
3007 return nickserv_delsslfp(cmd
, user
, user
->handle_info
, user
->sslfp
);
3009 return nickserv_delsslfp(cmd
, user
, user
->handle_info
, argv
[1]);
3013 static NICKSERV_FUNC(cmd_odelsslfp
)
3015 struct handle_info
*hi
;
3016 NICKSERV_MIN_PARMS(3);
3017 if (!(hi
= get_victim_oper(user
, argv
[1])))
3019 return nickserv_delsslfp(cmd
, user
, hi
, argv
[2]);
3023 nickserv_modify_handle_flags(struct userNode
*user
, struct userNode
*bot
, const char *str
, unsigned long *padded
, unsigned long *premoved
) {
3024 unsigned int nn
, add
= 1, pos
;
3025 unsigned long added
, removed
, flag
;
3027 for (added
=removed
=nn
=0; str
[nn
]; nn
++) {
3029 case '+': add
= 1; break;
3030 case '-': add
= 0; break;
3032 if (!(pos
= handle_inverse_flags
[(unsigned char)str
[nn
]])) {
3033 send_message(user
, bot
, "NSMSG_INVALID_FLAG", str
[nn
]);
3036 if (user
&& (user
->handle_info
->opserv_level
< flag_access_levels
[pos
-1])) {
3037 /* cheesy avoidance of looking up the flag name.. */
3038 send_message(user
, bot
, "NSMSG_FLAG_PRIVILEGED", str
[nn
]);
3041 flag
= 1 << (pos
- 1);
3043 added
|= flag
, removed
&= ~flag
;
3045 removed
|= flag
, added
&= ~flag
;
3050 *premoved
= removed
;
3055 nickserv_apply_flags(struct userNode
*user
, struct handle_info
*hi
, const char *flags
)
3057 unsigned long before
, after
, added
, removed
;
3058 struct userNode
*uNode
;
3060 before
= hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
);
3061 if (!nickserv_modify_handle_flags(user
, nickserv
, flags
, &added
, &removed
))
3063 hi
->flags
= (hi
->flags
| added
) & ~removed
;
3064 after
= hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
);
3066 /* Strip helping flag if they're only a support helper and not
3067 * currently in #support. */
3068 if (HANDLE_FLAGGED(hi
, HELPING
) && (after
== HI_FLAG_SUPPORT_HELPER
)) {
3069 struct channelList
*schannels
;
3071 schannels
= chanserv_support_channels();
3072 for (ii
= 0; ii
< schannels
->used
; ++ii
)
3073 if (find_handle_in_channel(schannels
->list
[ii
], hi
, NULL
))
3075 if (ii
== schannels
->used
)
3076 HANDLE_CLEAR_FLAG(hi
, HELPING
);
3079 if (after
&& !before
) {
3080 /* Add user to current helper list. */
3081 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
3082 userList_append(&curr_helpers
, uNode
);
3083 } else if (!after
&& before
) {
3084 /* Remove user from current helper list. */
3085 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
3086 userList_remove(&curr_helpers
, uNode
);
3093 set_list(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, int override
)
3097 char *set_display
[] = {
3098 "INFO", "WIDTH", "TABLEWIDTH", "COLOR", "PRIVMSG", "STYLE",
3099 "EMAIL", "ANNOUNCEMENTS", "AUTOHIDE", "MAXLOGINS", "LANGUAGE",
3100 "FAKEHOST", "TITLE", "EPITHET", "ADVANCED"
3103 reply("NSMSG_SETTING_LIST");
3104 reply("NSMSG_SETTING_LIST_HEADER");
3106 /* Do this so options are presented in a consistent order. */
3107 for (i
= 0; i
< ArrayLength(set_display
); ++i
)
3108 if ((opt
= dict_find(nickserv_opt_dict
, set_display
[i
], NULL
)))
3109 opt(cmd
, user
, hi
, override
, 0, NULL
);
3110 reply("NSMSG_SETTING_LIST_END");
3113 static NICKSERV_FUNC(cmd_set
)
3115 struct handle_info
*hi
;
3118 hi
= user
->handle_info
;
3120 set_list(cmd
, user
, hi
, 0);
3123 if (!(opt
= dict_find(nickserv_opt_dict
, argv
[1], NULL
))) {
3124 reply("NSMSG_INVALID_OPTION", argv
[1]);
3127 return opt(cmd
, user
, hi
, 0, argc
-1, argv
+1);
3130 static NICKSERV_FUNC(cmd_oset
)
3132 struct handle_info
*hi
;
3135 NICKSERV_MIN_PARMS(2);
3137 if (!(hi
= get_victim_oper(user
, argv
[1])))
3141 set_list(cmd
, user
, hi
, 0);
3145 if (!(opt
= dict_find(nickserv_opt_dict
, argv
[2], NULL
))) {
3146 reply("NSMSG_INVALID_OPTION", argv
[2]);
3150 return opt(cmd
, user
, hi
, 1, argc
-2, argv
+2);
3153 static OPTION_FUNC(opt_info
)
3157 if ((argv
[1][0] == '*') && (argv
[1][1] == 0)) {
3159 hi
->infoline
= NULL
;
3161 hi
->infoline
= strdup(unsplit_string(argv
+1, argc
-1, NULL
));
3165 info
= hi
->infoline
? hi
->infoline
: user_find_message(user
, "MSG_NONE");
3166 reply("NSMSG_SET_INFO", info
);
3170 static OPTION_FUNC(opt_width
)
3173 hi
->screen_width
= strtoul(argv
[1], NULL
, 0);
3175 if ((hi
->screen_width
> 0) && (hi
->screen_width
< MIN_LINE_SIZE
))
3176 hi
->screen_width
= MIN_LINE_SIZE
;
3177 else if (hi
->screen_width
> MAX_LINE_SIZE
)
3178 hi
->screen_width
= MAX_LINE_SIZE
;
3180 reply("NSMSG_SET_WIDTH", hi
->screen_width
);
3184 static OPTION_FUNC(opt_tablewidth
)
3187 hi
->table_width
= strtoul(argv
[1], NULL
, 0);
3189 if ((hi
->table_width
> 0) && (hi
->table_width
< MIN_LINE_SIZE
))
3190 hi
->table_width
= MIN_LINE_SIZE
;
3191 else if (hi
->screen_width
> MAX_LINE_SIZE
)
3192 hi
->table_width
= MAX_LINE_SIZE
;
3194 reply("NSMSG_SET_TABLEWIDTH", hi
->table_width
);
3198 static OPTION_FUNC(opt_color
)
3201 if (enabled_string(argv
[1]))
3202 HANDLE_SET_FLAG(hi
, MIRC_COLOR
);
3203 else if (disabled_string(argv
[1]))
3204 HANDLE_CLEAR_FLAG(hi
, MIRC_COLOR
);
3206 reply("MSG_INVALID_BINARY", argv
[1]);
3211 reply("NSMSG_SET_COLOR", user_find_message(user
, HANDLE_FLAGGED(hi
, MIRC_COLOR
) ? "MSG_ON" : "MSG_OFF"));
3215 static OPTION_FUNC(opt_privmsg
)
3218 if (enabled_string(argv
[1]))
3219 HANDLE_SET_FLAG(hi
, USE_PRIVMSG
);
3220 else if (disabled_string(argv
[1]))
3221 HANDLE_CLEAR_FLAG(hi
, USE_PRIVMSG
);
3223 reply("MSG_INVALID_BINARY", argv
[1]);
3228 reply("NSMSG_SET_PRIVMSG", user_find_message(user
, HANDLE_FLAGGED(hi
, USE_PRIVMSG
) ? "MSG_ON" : "MSG_OFF"));
3232 static OPTION_FUNC(opt_autohide
)
3235 if (enabled_string(argv
[1]))
3236 HANDLE_SET_FLAG(hi
, AUTOHIDE
);
3237 else if (disabled_string(argv
[1]))
3238 HANDLE_CLEAR_FLAG(hi
, AUTOHIDE
);
3240 reply("MSG_INVALID_BINARY", argv
[1]);
3245 reply("NSMSG_SET_AUTOHIDE", user_find_message(user
, HANDLE_FLAGGED(hi
, AUTOHIDE
) ? "MSG_ON" : "MSG_OFF"));
3249 static OPTION_FUNC(opt_style
)
3254 if (!irccasecmp(argv
[1], "Clean"))
3255 hi
->userlist_style
= HI_STYLE_CLEAN
;
3256 else if (!irccasecmp(argv
[1], "Advanced"))
3257 hi
->userlist_style
= HI_STYLE_ADVANCED
;
3258 else if (!irccasecmp(argv
[1], "Classic"))
3259 hi
->userlist_style
= HI_STYLE_CLASSIC
;
3260 else /* Default to normal */
3261 hi
->userlist_style
= HI_STYLE_NORMAL
;
3262 } /* TODO: give error if unknow style is chosen */
3264 switch (hi
->userlist_style
) {
3265 case HI_STYLE_ADVANCED
:
3268 case HI_STYLE_CLASSIC
:
3271 case HI_STYLE_CLEAN
:
3274 case HI_STYLE_NORMAL
:
3279 reply("NSMSG_SET_STYLE", style
);
3283 static OPTION_FUNC(opt_announcements
)
3288 if (enabled_string(argv
[1]))
3289 hi
->announcements
= 'y';
3290 else if (disabled_string(argv
[1]))
3291 hi
->announcements
= 'n';
3292 else if (!strcmp(argv
[1], "?") || !irccasecmp(argv
[1], "default"))
3293 hi
->announcements
= '?';
3295 reply("NSMSG_INVALID_ANNOUNCE", argv
[1]);
3300 switch (hi
->announcements
) {
3301 case 'y': choice
= user_find_message(user
, "MSG_ON"); break;
3302 case 'n': choice
= user_find_message(user
, "MSG_OFF"); break;
3303 case '?': choice
= "default"; break;
3304 default: choice
= "unknown"; break;
3306 reply("NSMSG_SET_ANNOUNCEMENTS", choice
);
3310 static OPTION_FUNC(opt_password
)
3312 char crypted
[MD5_CRYPT_LENGTH
+1];
3317 reply("NSMSG_USE_CMD_PASS");
3321 cryptpass(argv
[1], crypted
);
3323 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
3325 if((rc
= ldap_do_modify(hi
->handle
, crypted
, NULL
)) != LDAP_SUCCESS
) {
3326 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3331 strcpy(hi
->passwd
, crypted
);
3332 if (nickserv_conf
.sync_log
)
3333 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
3335 reply("NSMSG_SET_PASSWORD", "***");
3339 static OPTION_FUNC(opt_flags
)
3342 unsigned int ii
, flen
;
3345 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3350 nickserv_apply_flags(user
, hi
, argv
[1]);
3352 for (ii
= flen
= 0; handle_flags
[ii
]; ii
++)
3353 if (hi
->flags
& (1 << ii
))
3354 flags
[flen
++] = handle_flags
[ii
];
3357 reply("NSMSG_SET_FLAGS", flags
);
3359 reply("NSMSG_SET_FLAGS", user_find_message(user
, "MSG_NONE"));
3363 static OPTION_FUNC(opt_email
)
3367 if (!valid_email(argv
[1])) {
3368 reply("NSMSG_BAD_EMAIL_ADDR");
3371 if ((str
= mail_prohibited_address(argv
[1]))) {
3372 reply("NSMSG_EMAIL_PROHIBITED", argv
[1], str
);
3375 if (hi
->email_addr
&& !irccasecmp(hi
->email_addr
, argv
[1]))
3376 reply("NSMSG_EMAIL_SAME");
3378 nickserv_make_cookie(user
, hi
, EMAIL_CHANGE
, argv
[1], 0);
3381 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
3383 if((rc
= ldap_do_modify(hi
->handle
, NULL
, argv
[1])) != LDAP_SUCCESS
) {
3384 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3389 nickserv_set_email_addr(hi
, argv
[1]);
3391 nickserv_eat_cookie(hi
->cookie
);
3392 reply("NSMSG_SET_EMAIL", visible_email_addr(user
, hi
));
3395 reply("NSMSG_SET_EMAIL", visible_email_addr(user
, hi
));
3399 static OPTION_FUNC(opt_maxlogins
)
3401 unsigned char maxlogins
;
3403 maxlogins
= strtoul(argv
[1], NULL
, 0);
3404 if ((maxlogins
> nickserv_conf
.hard_maxlogins
) && !override
) {
3405 reply("NSMSG_BAD_MAX_LOGINS", nickserv_conf
.hard_maxlogins
);
3408 hi
->maxlogins
= maxlogins
;
3410 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
3411 reply("NSMSG_SET_MAXLOGINS", maxlogins
);
3415 static OPTION_FUNC(opt_advanced
)
3418 if (enabled_string(argv
[1]))
3419 HANDLE_SET_FLAG(hi
, ADVANCED
);
3420 else if (disabled_string(argv
[1]))
3421 HANDLE_CLEAR_FLAG(hi
, ADVANCED
);
3423 reply("MSG_INVALID_BINARY", argv
[1]);
3428 reply("NSMSG_SET_ADVANCED", user_find_message(user
, HANDLE_FLAGGED(hi
, ADVANCED
) ? "MSG_ON" : "MSG_OFF"));
3432 static OPTION_FUNC(opt_language
)
3434 struct language
*lang
;
3436 lang
= language_find(argv
[1]);
3437 if (irccasecmp(lang
->name
, argv
[1]))
3438 reply("NSMSG_LANGUAGE_NOT_FOUND", argv
[1], lang
->name
);
3439 hi
->language
= lang
;
3441 reply("NSMSG_SET_LANGUAGE", hi
->language
->name
);
3445 static OPTION_FUNC(opt_karma
)
3448 send_message(user
, nickserv
, "MSG_SETTING_PRIVILEGED", argv
[0]);
3453 if (argv
[1][0] == '+' && isdigit(argv
[1][1])) {
3454 hi
->karma
+= strtoul(argv
[1] + 1, NULL
, 10);
3455 } else if (argv
[1][0] == '-' && isdigit(argv
[1][1])) {
3456 hi
->karma
-= strtoul(argv
[1] + 1, NULL
, 10);
3458 send_message(user
, nickserv
, "NSMSG_INVALID_KARMA", argv
[1]);
3462 send_message(user
, nickserv
, "NSMSG_SET_KARMA", hi
->karma
);
3466 /* Called from opserv from cmd_access */
3468 oper_try_set_access(struct userNode
*user
, struct userNode
*bot
, struct handle_info
*target
, unsigned int new_level
) {
3469 if (!oper_has_access(user
, bot
, nickserv_conf
.modoper_level
, 0))
3471 if ((user
->handle_info
->opserv_level
< target
->opserv_level
)
3472 || ((user
->handle_info
->opserv_level
== target
->opserv_level
)
3473 && (user
->handle_info
->opserv_level
< 1000))) {
3474 send_message(user
, bot
, "MSG_USER_OUTRANKED", target
->handle
);
3477 if ((user
->handle_info
->opserv_level
< new_level
)
3478 || ((user
->handle_info
->opserv_level
== new_level
)
3479 && (user
->handle_info
->opserv_level
< 1000))) {
3480 send_message(user
, bot
, "NSMSG_OPSERV_LEVEL_BAD");
3483 if (user
->handle_info
== target
) {
3484 send_message(user
, bot
, "MSG_STUPID_ACCESS_CHANGE");
3488 if(nickserv_conf
.ldap_enable
&& *(nickserv_conf
.ldap_oper_group_dn
) && *(nickserv_conf
.ldap_admin_dn
)) {
3490 if(new_level
> nickserv_conf
.ldap_oper_group_level
)
3491 rc
= ldap_add2group(target
->handle
, nickserv_conf
.ldap_oper_group_dn
);
3493 rc
= ldap_delfromgroup(target
->handle
, nickserv_conf
.ldap_oper_group_dn
);
3494 if(rc
!= LDAP_SUCCESS
&& rc
!= LDAP_TYPE_OR_VALUE_EXISTS
&& rc
!= LDAP_NO_SUCH_ATTRIBUTE
) {
3495 send_message(user
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3499 if(nickserv_conf
.ldap_enable
&& *(nickserv_conf
.ldap_field_oslevel
) && *(nickserv_conf
.ldap_admin_dn
)) {
3501 if((rc
= ldap_do_oslevel(target
->handle
, new_level
, target
->opserv_level
)) != LDAP_SUCCESS
) {
3502 send_message(user
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3507 if (target
->opserv_level
== new_level
)
3509 log_module(NS_LOG
, LOG_INFO
, "Account %s setting oper level for account %s to %d (from %d).",
3510 user
->handle_info
->handle
, target
->handle
, new_level
, target
->opserv_level
);
3511 target
->opserv_level
= new_level
;
3515 static OPTION_FUNC(opt_level
)
3520 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3524 res
= (argc
> 1) ? oper_try_set_access(user
, nickserv
, hi
, strtoul(argv
[1], NULL
, 0)) : 0;
3525 reply("NSMSG_SET_LEVEL", hi
->opserv_level
);
3529 static OPTION_FUNC(opt_epithet
)
3531 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_epithet_level
, 0)) {
3533 struct userNode
*target
, *next_un
;
3536 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3540 epithet
= unsplit_string(argv
+1, argc
-1, NULL
);
3544 if ((epithet
[0] == '*') && !epithet
[1])
3547 hi
->epithet
= strdup(epithet
);
3549 for (target
= hi
->users
; target
; target
= next_un
) {
3550 irc_swhois(nickserv
, target
, hi
->epithet
);
3552 next_un
= target
->next_authed
;
3557 reply("NSMSG_SET_EPITHET", hi
->epithet
);
3559 reply("NSMSG_SET_EPITHET", user_find_message(user
, "MSG_NONE"));
3563 static OPTION_FUNC(opt_title
)
3569 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_title_level
, 0)) {
3571 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3576 if(!strcmp(title
, "*")) {
3578 hi
->fakehost
= NULL
;
3581 if (strchr(title
, '.')) {
3582 reply("NSMSG_TITLE_INVALID");
3585 /* Alphanumeric titles only. */
3586 for(sptr
= title
; *sptr
; sptr
++) {
3587 if(!isalnum(*sptr
) && *sptr
!= '-') {
3588 reply("NSMSG_TITLE_INVALID");
3592 if ((strlen(user
->handle_info
->handle
) + strlen(title
) +
3593 strlen(nickserv_conf
.titlehost_suffix
) + 2) > HOSTLEN
) {
3594 reply("NSMSG_TITLE_TRUNCATED");
3598 hi
->fakehost
= malloc(strlen(title
)+2);
3599 hi
->fakehost
[0] = '.';
3600 strcpy(hi
->fakehost
+1, title
);
3603 } else if (hi
->fakehost
&& (hi
->fakehost
[0] == '.'))
3604 title
= hi
->fakehost
+ 1;
3606 /* If theres no title set then the default title will therefore
3607 be the first part of hidden_host in x3.conf, so for
3608 consistency with opt_fakehost we will print this here.
3609 This isnt actually used in P10, its just handled to keep from crashing... */
3610 char *hs
, *hidden_suffix
, *rest
;
3612 hs
= conf_get_data("server/hidden_host", RECDB_QSTRING
);
3613 hidden_suffix
= strdup(hs
);
3615 /* Yes we do this twice */
3616 if((rest
= strchr(hidden_suffix
, '.')))
3619 title
= hidden_suffix
;
3623 /* A lame default if someone configured hidden_host to something lame */
3624 title
= strdup("users");
3625 free(hidden_suffix
);
3631 none
= user_find_message(user
, "MSG_NONE");
3632 send_message(user
, nickserv
, "NSMSG_SET_TITLE", title
? title
: none
);
3637 check_vhost(char *vhost
, struct userNode
*user
, struct svccmd
*cmd
)
3641 // check for a dot in the vhost
3642 if(strchr(vhost
, '.') == NULL
) {
3643 reply("NSMSG_NOT_VALID_FAKEHOST_DOT", vhost
);
3647 // check for a @ in the vhost
3648 if(strchr(vhost
, '@') != NULL
) {
3649 reply("NSMSG_NOT_VALID_FAKEHOST_AT", vhost
);
3653 // check for denied words, inspired by monk at paki.sex
3654 for(y
= 0; y
< nickserv_conf
.denied_fakehost_words
->used
; y
++) {
3655 if(strstr(vhost
, nickserv_conf
.denied_fakehost_words
->list
[y
]) != NULL
) {
3656 reply("NSMSG_DENIED_FAKEHOST_WORD", vhost
, nickserv_conf
.denied_fakehost_words
->list
[y
]);
3661 // check for ircu's HOSTLEN length.
3662 if(strlen(vhost
) >= HOSTLEN
) {
3663 reply("NSMSG_NOT_VALID_FAKEHOST_LEN", vhost
);
3667 /* This can be handled by the regex now if desired.
3668 if (vhost[strspn(vhost, "0123456789.")]) {
3669 hostname = vhost + strlen(vhost);
3670 for (depth = 1; depth && (hostname > vhost); depth--) {
3672 while ((hostname > vhost) && (*hostname != '.')) hostname--;
3675 if (*hostname == '.') hostname++; * advance past last dot we saw *
3676 if(strlen(hostname) > 4) {
3677 reply("NSMSG_NOT_VALID_FAKEHOST_TLD_LEN", vhost);
3682 /* test either regex or as valid handle */
3683 if (nickserv_conf
.valid_fakehost_regex_set
) {
3684 int err
= regexec(&nickserv_conf
.valid_fakehost_regex
, vhost
, 0, 0, 0);
3687 buff
[regerror(err
, &nickserv_conf
.valid_fakehost_regex
, buff
, sizeof(buff
))] = 0;
3688 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
3690 if(err
== REG_NOMATCH
) {
3691 reply("NSMSG_NOT_VALID_FAKEHOST_REGEX", vhost
);
3700 static OPTION_FUNC(opt_fakehost
)
3704 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_fakehost_level
, 0)) {
3706 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3711 if ((strlen(fake
) > HOSTLEN
) || (fake
[0] == '.')) {
3712 reply("NSMSG_FAKEHOST_INVALID", HOSTLEN
);
3715 if (!strcmp(fake
, "*")) {
3718 hi
->fakehost
= NULL
;
3721 else if (!check_vhost(argv
[1], user
, cmd
)) {
3722 /* check_vhost takes care of error reply */
3728 hi
->fakehost
= strdup(fake
);
3731 fake
= hi
->fakehost
;
3733 fake
= generate_fakehost(hi
);
3735 /* Tell them we set the host */
3737 fake
= user_find_message(user
, "MSG_NONE");
3738 reply("NSMSG_SET_FAKEHOST", fake
);
3742 static OPTION_FUNC(opt_note
)
3745 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3750 char *text
= unsplit_string(argv
+ 1, argc
- 1, NULL
);
3755 if ((text
[0] == '*') && !text
[1])
3758 if (!(hi
->note
= nickserv_add_note(user
->handle_info
->handle
, now
, text
)))
3763 reply("NSMSG_SET_NOTE", hi
->note
? hi
->note
->note
: user_find_message(user
, "MSG_NONE"));
3767 static NICKSERV_FUNC(cmd_reclaim
)
3769 struct handle_info
*hi
;
3770 struct nick_info
*ni
;
3771 struct userNode
*victim
;
3773 NICKSERV_MIN_PARMS(2);
3774 hi
= user
->handle_info
;
3775 ni
= dict_find(nickserv_nick_dict
, argv
[1], 0);
3777 reply("NSMSG_UNKNOWN_NICK", argv
[1]);
3780 if (ni
->owner
!= user
->handle_info
) {
3781 reply("NSMSG_NOT_YOUR_NICK", ni
->nick
);
3784 victim
= GetUserH(ni
->nick
);
3786 reply("MSG_NICK_UNKNOWN", ni
->nick
);
3789 if (victim
== user
) {
3790 reply("NSMSG_NICK_USER_YOU");
3793 nickserv_reclaim(victim
, ni
, nickserv_conf
.reclaim_action
);
3794 switch (nickserv_conf
.reclaim_action
) {
3795 case RECLAIM_NONE
: reply("NSMSG_RECLAIMED_NONE"); break;
3796 case RECLAIM_WARN
: reply("NSMSG_RECLAIMED_WARN", victim
->nick
); break;
3797 case RECLAIM_SVSNICK
: reply("NSMSG_RECLAIMED_SVSNICK", victim
->nick
); break;
3798 case RECLAIM_KILL
: reply("NSMSG_RECLAIMED_KILL", victim
->nick
); break;
3803 static NICKSERV_FUNC(cmd_unregnick
)
3806 struct handle_info
*hi
;
3807 struct nick_info
*ni
;
3809 hi
= user
->handle_info
;
3810 nick
= (argc
< 2) ? user
->nick
: (const char*)argv
[1];
3811 ni
= dict_find(nickserv_nick_dict
, nick
, NULL
);
3813 reply("NSMSG_UNKNOWN_NICK", nick
);
3816 if (hi
!= ni
->owner
) {
3817 reply("NSMSG_NOT_YOUR_NICK", nick
);
3820 reply("NSMSG_UNREGNICK_SUCCESS", ni
->nick
);
3825 static NICKSERV_FUNC(cmd_ounregnick
)
3827 struct nick_info
*ni
;
3829 NICKSERV_MIN_PARMS(2);
3830 if (!(ni
= get_nick_info(argv
[1]))) {
3831 reply("NSMSG_NICK_NOT_REGISTERED", argv
[1]);
3834 if (!oper_outranks(user
, ni
->owner
))
3836 reply("NSMSG_UNREGNICK_SUCCESS", ni
->nick
);
3841 static NICKSERV_FUNC(cmd_unregister
)
3843 struct handle_info
*hi
;
3846 NICKSERV_MIN_PARMS(2);
3847 hi
= user
->handle_info
;
3850 if (checkpass(passwd
, hi
->passwd
)) {
3851 if(nickserv_unregister_handle(hi
, user
, cmd
->parent
->bot
))
3856 log_module(NS_LOG
, LOG_INFO
, "Account '%s' tried to unregister with the wrong password.", hi
->handle
);
3857 reply("NSMSG_PASSWORD_INVALID");
3862 static NICKSERV_FUNC(cmd_ounregister
)
3864 struct handle_info
*hi
;
3865 char reason
[MAXLEN
];
3868 NICKSERV_MIN_PARMS(2);
3869 if (!(hi
= get_victim_oper(user
, argv
[1])))
3872 if (HANDLE_FLAGGED(hi
, NODELETE
)) {
3873 reply("NSMSG_UNREGISTER_NODELETE", hi
->handle
);
3877 force
= IsOper(user
) && (argc
> 2) && !irccasecmp(argv
[2], "force");
3879 ((hi
->flags
& nickserv_conf
.ounregister_flags
)
3881 || (hi
->last_quit_host
[0] && ((unsigned)(now
- hi
->lastseen
) < nickserv_conf
.ounregister_inactive
)))) {
3882 reply((IsOper(user
) ? "NSMSG_UNREGISTER_MUST_FORCE" : "NSMSG_UNREGISTER_CANNOT_FORCE"), hi
->handle
);
3885 snprintf(reason
, sizeof(reason
), "%s unregistered account %s.", user
->handle_info
->handle
, hi
->handle
);
3886 global_message(MESSAGE_RECIPIENT_STAFF
, reason
);
3887 if(nickserv_unregister_handle(hi
, user
, cmd
->parent
->bot
))
3893 static NICKSERV_FUNC(cmd_status
)
3895 if (nickserv_conf
.disable_nicks
) {
3896 reply("NSMSG_GLOBAL_STATS_NONICK",
3897 dict_size(nickserv_handle_dict
));
3899 if (user
->handle_info
) {
3901 struct nick_info
*ni
;
3902 for (ni
=user
->handle_info
->nicks
; ni
; ni
=ni
->next
) cnt
++;
3903 reply("NSMSG_HANDLE_STATS", cnt
);
3905 reply("NSMSG_HANDLE_NONE");
3907 reply("NSMSG_GLOBAL_STATS",
3908 dict_size(nickserv_handle_dict
),
3909 dict_size(nickserv_nick_dict
));
3914 static NICKSERV_FUNC(cmd_ghost
)
3916 struct userNode
*target
;
3917 char reason
[MAXLEN
];
3919 NICKSERV_MIN_PARMS(2);
3920 if (!(target
= GetUserH(argv
[1]))) {
3921 reply("MSG_NICK_UNKNOWN", argv
[1]);
3924 if (target
== user
) {
3925 reply("NSMSG_CANNOT_GHOST_SELF");
3928 if (!target
->handle_info
|| (target
->handle_info
!= user
->handle_info
)) {
3929 reply("NSMSG_CANNOT_GHOST_USER", target
->nick
);
3932 snprintf(reason
, sizeof(reason
), "Ghost kill on account %s (requested by %s).", target
->handle_info
->handle
, user
->nick
);
3933 DelUser(target
, nickserv
, 1, reason
);
3934 reply("NSMSG_GHOST_KILLED", argv
[1]);
3938 static NICKSERV_FUNC(cmd_vacation
)
3940 HANDLE_SET_FLAG(user
->handle_info
, FROZEN
);
3941 reply("NSMSG_ON_VACATION");
3946 nickserv_saxdb_write(struct saxdb_context
*ctx
) {
3948 struct handle_info
*hi
;
3951 for (it
= dict_first(nickserv_handle_dict
); it
; it
= iter_next(it
)) {
3953 saxdb_start_record(ctx
, iter_key(it
), 0);
3954 if (hi
->announcements
!= '?') {
3955 flags
[0] = hi
->announcements
;
3957 saxdb_write_string(ctx
, KEY_ANNOUNCEMENTS
, flags
);
3960 struct handle_cookie
*cookie
= hi
->cookie
;
3963 switch (cookie
->type
) {
3964 case ACTIVATION
: type
= KEY_ACTIVATION
; break;
3965 case PASSWORD_CHANGE
: type
= KEY_PASSWORD_CHANGE
; break;
3966 case EMAIL_CHANGE
: type
= KEY_EMAIL_CHANGE
; break;
3967 case ALLOWAUTH
: type
= KEY_ALLOWAUTH
; break;
3968 default: type
= NULL
; break;
3971 saxdb_start_record(ctx
, KEY_COOKIE
, 0);
3972 saxdb_write_string(ctx
, KEY_COOKIE_TYPE
, type
);
3973 saxdb_write_int(ctx
, KEY_COOKIE_EXPIRES
, cookie
->expires
);
3975 saxdb_write_string(ctx
, KEY_COOKIE_DATA
, cookie
->data
);
3976 saxdb_write_string(ctx
, KEY_COOKIE
, cookie
->cookie
);
3977 saxdb_end_record(ctx
);
3981 saxdb_write_string(ctx
, KEY_EMAIL_ADDR
, hi
->email_addr
);
3983 saxdb_write_string(ctx
, KEY_EPITHET
, hi
->epithet
);
3985 saxdb_start_record(ctx
, KEY_NOTE_NOTE
, 0);
3986 saxdb_write_string(ctx
, KEY_NOTE_SETTER
, hi
->note
->setter
);
3987 saxdb_write_int(ctx
, KEY_NOTE_DATE
, hi
->note
->date
);
3988 saxdb_write_string(ctx
, KEY_NOTE_NOTE
, hi
->note
->note
);
3989 saxdb_end_record(ctx
);
3993 saxdb_write_string(ctx
, KEY_FAKEHOST
, hi
->fakehost
);
3997 for (ii
=flen
=0; handle_flags
[ii
]; ++ii
)
3998 if (hi
->flags
& (1 << ii
))
3999 flags
[flen
++] = handle_flags
[ii
];
4001 saxdb_write_string(ctx
, KEY_FLAGS
, flags
);
4004 saxdb_write_string(ctx
, KEY_INFO
, hi
->infoline
);
4005 if (hi
->last_quit_host
[0])
4006 saxdb_write_string(ctx
, KEY_LAST_QUIT_HOST
, hi
->last_quit_host
);
4007 saxdb_write_int(ctx
, KEY_LAST_SEEN
, hi
->lastseen
);
4009 saxdb_write_sint(ctx
, KEY_KARMA
, hi
->karma
);
4010 if (hi
->masks
->used
)
4011 saxdb_write_string_list(ctx
, KEY_MASKS
, hi
->masks
);
4012 if (hi
->sslfps
->used
)
4013 saxdb_write_string_list(ctx
, KEY_SSLFPS
, hi
->sslfps
);
4014 if (hi
->ignores
->used
)
4015 saxdb_write_string_list(ctx
, KEY_IGNORES
, hi
->ignores
);
4017 saxdb_write_int(ctx
, KEY_MAXLOGINS
, hi
->maxlogins
);
4019 struct string_list
*slist
;
4020 struct nick_info
*ni
;
4022 slist
= alloc_string_list(nickserv_conf
.nicks_per_handle
);
4023 for (ni
= hi
->nicks
; ni
; ni
= ni
->next
) string_list_append(slist
, ni
->nick
);
4024 saxdb_write_string_list(ctx
, KEY_NICKS
, slist
);
4028 if (hi
->opserv_level
)
4029 saxdb_write_int(ctx
, KEY_OPSERV_LEVEL
, hi
->opserv_level
);
4030 if (hi
->language
!= lang_C
)
4031 saxdb_write_string(ctx
, KEY_LANGUAGE
, hi
->language
->name
);
4032 saxdb_write_string(ctx
, KEY_PASSWD
, hi
->passwd
);
4033 saxdb_write_int(ctx
, KEY_REGISTER_ON
, hi
->registered
);
4034 if (hi
->screen_width
)
4035 saxdb_write_int(ctx
, KEY_SCREEN_WIDTH
, hi
->screen_width
);
4036 if (hi
->table_width
)
4037 saxdb_write_int(ctx
, KEY_TABLE_WIDTH
, hi
->table_width
);
4038 flags
[0] = hi
->userlist_style
;
4040 saxdb_write_string(ctx
, KEY_USERLIST_STYLE
, flags
);
4041 saxdb_end_record(ctx
);
4047 static handle_merge_func_t
*handle_merge_func_list
;
4048 static void **handle_merge_func_list_extra
;
4049 static unsigned int handle_merge_func_size
= 0, handle_merge_func_used
= 0;
4052 reg_handle_merge_func(handle_merge_func_t func
, void *extra
)
4054 if (handle_merge_func_used
== handle_merge_func_size
) {
4055 if (handle_merge_func_size
) {
4056 handle_merge_func_size
<<= 1;
4057 handle_merge_func_list
= realloc(handle_merge_func_list
, handle_merge_func_size
*sizeof(handle_merge_func_t
));
4058 handle_merge_func_list_extra
= realloc(handle_merge_func_list_extra
, handle_merge_func_size
*sizeof(void*));
4060 handle_merge_func_size
= 8;
4061 handle_merge_func_list
= malloc(handle_merge_func_size
*sizeof(handle_merge_func_t
));
4062 handle_merge_func_list_extra
= malloc(handle_merge_func_size
*sizeof(void*));
4065 handle_merge_func_list
[handle_merge_func_used
] = func
;
4066 handle_merge_func_list_extra
[handle_merge_func_used
++] = extra
;
4069 static NICKSERV_FUNC(cmd_merge
)
4071 struct handle_info
*hi_from
, *hi_to
;
4072 struct userNode
*last_user
;
4073 struct userData
*cList
, *cListNext
;
4074 unsigned int ii
, jj
, n
;
4076 NICKSERV_MIN_PARMS(3);
4078 if (!(hi_from
= get_victim_oper(user
, argv
[1])))
4080 if (!(hi_to
= get_victim_oper(user
, argv
[2])))
4082 if (hi_to
== hi_from
) {
4083 reply("NSMSG_CANNOT_MERGE_SELF", hi_to
->handle
);
4087 for (n
=0; n
<handle_merge_func_used
; n
++)
4088 handle_merge_func_list
[n
](user
, hi_to
, hi_from
, handle_merge_func_list_extra
[n
]);
4090 /* Append "from" handle's nicks to "to" handle's nick list. */
4092 struct nick_info
*last_ni
;
4093 for (last_ni
=hi_to
->nicks
; last_ni
->next
; last_ni
=last_ni
->next
) ;
4094 last_ni
->next
= hi_from
->nicks
;
4096 while (hi_from
->nicks
) {
4097 hi_from
->nicks
->owner
= hi_to
;
4098 hi_from
->nicks
= hi_from
->nicks
->next
;
4101 /* Merge the hostmasks. */
4102 for (ii
=0; ii
<hi_from
->masks
->used
; ii
++) {
4103 char *mask
= hi_from
->masks
->list
[ii
];
4104 for (jj
=0; jj
<hi_to
->masks
->used
; jj
++)
4105 if (match_ircglobs(hi_to
->masks
->list
[jj
], mask
))
4107 if (jj
==hi_to
->masks
->used
) /* Nothing from the "to" handle covered this mask, so add it. */
4108 string_list_append(hi_to
->masks
, strdup(mask
));
4111 /* Merge the ignores. */
4112 for (ii
=0; ii
<hi_from
->ignores
->used
; ii
++) {
4113 char *ignore
= hi_from
->ignores
->list
[ii
];
4114 for (jj
=0; jj
<hi_to
->ignores
->used
; jj
++)
4115 if (match_ircglobs(hi_to
->ignores
->list
[jj
], ignore
))
4117 if (jj
==hi_to
->ignores
->used
) /* Nothing from the "to" handle covered this mask, so add it. */
4118 string_list_append(hi_to
->ignores
, strdup(ignore
));
4121 /* Merge the lists of authed users. */
4123 for (last_user
=hi_to
->users
; last_user
->next_authed
; last_user
=last_user
->next_authed
) ;
4124 last_user
->next_authed
= hi_from
->users
;
4126 hi_to
->users
= hi_from
->users
;
4128 /* Repoint the old "from" handle's users. */
4129 for (last_user
=hi_from
->users
; last_user
; last_user
=last_user
->next_authed
) {
4130 last_user
->handle_info
= hi_to
;
4132 hi_from
->users
= NULL
;
4134 /* Merge channel userlists. */
4135 for (cList
=hi_from
->channels
; cList
; cList
=cListNext
) {
4136 struct userData
*cList2
;
4137 cListNext
= cList
->u_next
;
4138 for (cList2
=hi_to
->channels
; cList2
; cList2
=cList2
->u_next
)
4139 if (cList
->channel
== cList2
->channel
)
4141 if (cList2
&& (cList2
->access
>= cList
->access
)) {
4142 log_module(NS_LOG
, LOG_INFO
, "Merge: %s had only %d access in %s (versus %d for %s)", hi_from
->handle
, cList
->access
, cList
->channel
->channel
->name
, cList2
->access
, hi_to
->handle
);
4143 /* keep cList2 in hi_to; remove cList from hi_from */
4144 del_channel_user(cList
, 1);
4147 log_module(NS_LOG
, LOG_INFO
, "Merge: %s had only %d access in %s (versus %d for %s)", hi_to
->handle
, cList2
->access
, cList
->channel
->channel
->name
, cList
->access
, hi_from
->handle
);
4148 /* remove the lower-ranking cList2 from hi_to */
4149 del_channel_user(cList2
, 1);
4151 log_module(NS_LOG
, LOG_INFO
, "Merge: %s had no access in %s", hi_to
->handle
, cList
->channel
->channel
->name
);
4153 /* cList needs to be moved from hi_from to hi_to */
4154 cList
->handle
= hi_to
;
4155 /* Remove from linked list for hi_from */
4156 assert(!cList
->u_prev
);
4157 hi_from
->channels
= cList
->u_next
;
4159 cList
->u_next
->u_prev
= cList
->u_prev
;
4160 /* Add to linked list for hi_to */
4161 cList
->u_prev
= NULL
;
4162 cList
->u_next
= hi_to
->channels
;
4163 if (hi_to
->channels
)
4164 hi_to
->channels
->u_prev
= cList
;
4165 hi_to
->channels
= cList
;
4169 /* Do they get an OpServ level promotion? */
4170 if (hi_from
->opserv_level
> hi_to
->opserv_level
)
4171 hi_to
->opserv_level
= hi_from
->opserv_level
;
4173 /* What about last seen time? */
4174 if (hi_from
->lastseen
> hi_to
->lastseen
)
4175 hi_to
->lastseen
= hi_from
->lastseen
;
4177 /* New karma is the sum of the two original karmas. */
4178 hi_to
->karma
+= hi_from
->karma
;
4180 /* Does a fakehost carry over? (This intentionally doesn't set it
4181 * for users previously attached to hi_to. They'll just have to
4184 if (hi_from
->fakehost
&& !hi_to
->fakehost
)
4185 hi_to
->fakehost
= strdup(hi_from
->fakehost
);
4187 /* Notify of success. */
4188 reply("NSMSG_HANDLES_MERGED", hi_from
->handle
, hi_to
->handle
);
4189 global_message_args(MESSAGE_RECIPIENT_OPERS
, "NSMSG_ACCOUNT_MERGED", user
->nick
,
4190 user
->handle_info
->handle
, hi_from
->handle
, hi_to
->handle
);
4192 /* Unregister the "from" handle. */
4193 nickserv_unregister_handle(hi_from
, NULL
, cmd
->parent
->bot
);
4194 /* TODO: fix it so that if the ldap delete in nickserv_unregister_handle fails,
4195 * the process isn't completed.
4201 struct nickserv_discrim
{
4202 unsigned long flags_on
, flags_off
;
4203 time_t min_registered
, max_registered
;
4206 int min_level
, max_level
;
4207 int min_karma
, max_karma
;
4208 enum { SUBSET
, EXACT
, SUPERSET
, LASTQUIT
} hostmask_type
;
4209 const char *nickmask
;
4210 const char *hostmask
;
4211 const char *handlemask
;
4212 const char *emailmask
;
4214 unsigned int inldap
;
4218 typedef void (*discrim_search_func
)(struct userNode
*source
, struct handle_info
*hi
);
4220 struct discrim_apply_info
{
4221 struct nickserv_discrim
*discrim
;
4222 discrim_search_func func
;
4223 struct userNode
*source
;
4224 unsigned int matched
;
4227 static struct nickserv_discrim
*
4228 nickserv_discrim_create(struct svccmd
*cmd
, struct userNode
*user
, unsigned int argc
, char *argv
[])
4231 struct nickserv_discrim
*discrim
;
4233 discrim
= malloc(sizeof(*discrim
));
4234 memset(discrim
, 0, sizeof(*discrim
));
4235 discrim
->min_level
= 0;
4236 discrim
->max_level
= INT_MAX
;
4237 discrim
->limit
= 50;
4238 discrim
->min_registered
= 0;
4239 discrim
->max_registered
= INT_MAX
;
4240 discrim
->lastseen
= LONG_MAX
;
4241 discrim
->min_karma
= INT_MIN
;
4242 discrim
->max_karma
= INT_MAX
;
4244 discrim
->inldap
= 2;
4247 for (i
=0; i
<argc
; i
++) {
4248 if (i
== argc
- 1) {
4249 reply("MSG_MISSING_PARAMS", argv
[i
]);
4252 if (!irccasecmp(argv
[i
], "limit")) {
4253 discrim
->limit
= strtoul(argv
[++i
], NULL
, 0);
4254 } else if (!irccasecmp(argv
[i
], "flags")) {
4255 nickserv_modify_handle_flags(user
, nickserv
, argv
[++i
], &discrim
->flags_on
, &discrim
->flags_off
);
4256 } else if (!irccasecmp(argv
[i
], "registered")) {
4257 const char *cmp
= argv
[++i
];
4258 if (cmp
[0] == '<') {
4259 if (cmp
[1] == '=') {
4260 discrim
->min_registered
= now
- ParseInterval(cmp
+2);
4262 discrim
->min_registered
= now
- ParseInterval(cmp
+1) + 1;
4264 } else if (cmp
[0] == '=') {
4265 discrim
->min_registered
= discrim
->max_registered
= now
- ParseInterval(cmp
+1);
4266 } else if (cmp
[0] == '>') {
4267 if (cmp
[1] == '=') {
4268 discrim
->max_registered
= now
- ParseInterval(cmp
+2);
4270 discrim
->max_registered
= now
- ParseInterval(cmp
+1) - 1;
4273 reply("MSG_INVALID_CRITERIA", cmp
);
4275 } else if (!irccasecmp(argv
[i
], "seen")) {
4276 discrim
->lastseen
= now
- ParseInterval(argv
[++i
]);
4277 } else if (!nickserv_conf
.disable_nicks
&& !irccasecmp(argv
[i
], "nickmask")) {
4278 discrim
->nickmask
= argv
[++i
];
4279 } else if (!irccasecmp(argv
[i
], "hostmask")) {
4281 if (!irccasecmp(argv
[i
], "exact")) {
4282 if (i
== argc
- 1) {
4283 reply("MSG_MISSING_PARAMS", argv
[i
]);
4286 discrim
->hostmask_type
= EXACT
;
4287 } else if (!irccasecmp(argv
[i
], "subset")) {
4288 if (i
== argc
- 1) {
4289 reply("MSG_MISSING_PARAMS", argv
[i
]);
4292 discrim
->hostmask_type
= SUBSET
;
4293 } else if (!irccasecmp(argv
[i
], "superset")) {
4294 if (i
== argc
- 1) {
4295 reply("MSG_MISSING_PARAMS", argv
[i
]);
4298 discrim
->hostmask_type
= SUPERSET
;
4299 } else if (!irccasecmp(argv
[i
], "lastquit") || !irccasecmp(argv
[i
], "lastauth")) {
4300 if (i
== argc
- 1) {
4301 reply("MSG_MISSING_PARAMS", argv
[i
]);
4304 discrim
->hostmask_type
= LASTQUIT
;
4307 discrim
->hostmask_type
= SUPERSET
;
4309 discrim
->hostmask
= argv
[++i
];
4310 } else if (!irccasecmp(argv
[i
], "handlemask") || !irccasecmp(argv
[i
], "accountmask") || !irccasecmp(argv
[i
], "account")) {
4311 if (!irccasecmp(argv
[++i
], "*")) {
4312 discrim
->handlemask
= 0;
4314 discrim
->handlemask
= argv
[i
];
4316 } else if (!irccasecmp(argv
[i
], "email")) {
4317 if (user
->handle_info
->opserv_level
< nickserv_conf
.email_search_level
) {
4318 reply("MSG_NO_SEARCH_ACCESS", "email");
4320 } else if (!irccasecmp(argv
[++i
], "*")) {
4321 discrim
->emailmask
= 0;
4323 discrim
->emailmask
= argv
[i
];
4325 } else if (!irccasecmp(argv
[i
], "access")) {
4326 const char *cmp
= argv
[++i
];
4327 if (cmp
[0] == '<') {
4328 if (discrim
->min_level
== 0) discrim
->min_level
= 1;
4329 if (cmp
[1] == '=') {
4330 discrim
->max_level
= strtoul(cmp
+2, NULL
, 0);
4332 discrim
->max_level
= strtoul(cmp
+1, NULL
, 0) - 1;
4334 } else if (cmp
[0] == '=') {
4335 discrim
->min_level
= discrim
->max_level
= strtoul(cmp
+1, NULL
, 0);
4336 } else if (cmp
[0] == '>') {
4337 if (cmp
[1] == '=') {
4338 discrim
->min_level
= strtoul(cmp
+2, NULL
, 0);
4340 discrim
->min_level
= strtoul(cmp
+1, NULL
, 0) + 1;
4343 reply("MSG_INVALID_CRITERIA", cmp
);
4345 } else if (!irccasecmp(argv
[i
], "karma")) {
4346 const char *cmp
= argv
[++i
];
4347 if (cmp
[0] == '<') {
4348 if (cmp
[1] == '=') {
4349 discrim
->max_karma
= strtoul(cmp
+2, NULL
, 0);
4351 discrim
->max_karma
= strtoul(cmp
+1, NULL
, 0) - 1;
4353 } else if (cmp
[0] == '=') {
4354 discrim
->min_karma
= discrim
->max_karma
= strtoul(cmp
+1, NULL
, 0);
4355 } else if (cmp
[0] == '>') {
4356 if (cmp
[1] == '=') {
4357 discrim
->min_karma
= strtoul(cmp
+2, NULL
, 0);
4359 discrim
->min_karma
= strtoul(cmp
+1, NULL
, 0) + 1;
4362 send_message(user
, nickserv
, "MSG_INVALID_CRITERIA", cmp
);
4365 } else if (nickserv_conf
.ldap_enable
&& !irccasecmp(argv
[i
], "inldap")) {
4367 if(true_string(argv
[i
])) {
4368 discrim
->inldap
= 1;
4370 else if (false_string(argv
[i
])) {
4371 discrim
->inldap
= 0;
4374 reply("MSG_INVALID_BINARY", argv
[i
]);
4378 reply("MSG_INVALID_CRITERIA", argv
[i
]);
4389 nickserv_discrim_match(struct nickserv_discrim
*discrim
, struct handle_info
*hi
)
4391 if (((discrim
->flags_on
& hi
->flags
) != discrim
->flags_on
)
4392 || (discrim
->flags_off
& hi
->flags
)
4393 || (discrim
->min_registered
> hi
->registered
)
4394 || (discrim
->max_registered
< hi
->registered
)
4395 || (discrim
->lastseen
< (hi
->users
?now
:hi
->lastseen
))
4396 || (discrim
->handlemask
&& !match_ircglob(hi
->handle
, discrim
->handlemask
))
4397 || (discrim
->emailmask
&& (!hi
->email_addr
|| !match_ircglob(hi
->email_addr
, discrim
->emailmask
)))
4398 || (discrim
->min_level
> hi
->opserv_level
)
4399 || (discrim
->max_level
< hi
->opserv_level
)
4400 || (discrim
->min_karma
> hi
->karma
)
4401 || (discrim
->max_karma
< hi
->karma
)
4405 if (discrim
->hostmask
) {
4407 for (i
=0; i
<hi
->masks
->used
; i
++) {
4408 const char *mask
= hi
->masks
->list
[i
];
4409 if ((discrim
->hostmask_type
== SUBSET
)
4410 && (match_ircglobs(discrim
->hostmask
, mask
))) break;
4411 else if ((discrim
->hostmask_type
== EXACT
)
4412 && !irccasecmp(discrim
->hostmask
, mask
)) break;
4413 else if ((discrim
->hostmask_type
== SUPERSET
)
4414 && (match_ircglobs(mask
, discrim
->hostmask
))) break;
4415 else if ((discrim
->hostmask_type
== LASTQUIT
)
4416 && (match_ircglobs(discrim
->hostmask
, hi
->last_quit_host
))) break;
4418 if (i
==hi
->masks
->used
) return 0;
4420 if (discrim
->nickmask
) {
4421 struct nick_info
*nick
= hi
->nicks
;
4423 if (match_ircglob(nick
->nick
, discrim
->nickmask
)) break;
4426 if (!nick
) return 0;
4429 if(nickserv_conf
.ldap_enable
&& discrim
->inldap
!= 2) {
4431 rc
= ldap_get_user_info(hi
->handle
, NULL
);
4432 if(discrim
->inldap
== 1 && rc
!= LDAP_SUCCESS
)
4434 if(discrim
->inldap
== 0 && rc
== LDAP_SUCCESS
)
4443 nickserv_discrim_search(struct nickserv_discrim
*discrim
, discrim_search_func dsf
, struct userNode
*source
)
4445 dict_iterator_t it
, next
;
4446 unsigned int matched
;
4448 for (it
= dict_first(nickserv_handle_dict
), matched
= 0;
4449 it
&& (matched
< discrim
->limit
);
4451 next
= iter_next(it
);
4452 if (nickserv_discrim_match(discrim
, iter_data(it
))) {
4453 dsf(source
, iter_data(it
));
4461 search_print_func(struct userNode
*source
, struct handle_info
*match
)
4463 send_message(source
, nickserv
, "NSMSG_SEARCH_MATCH", match
->handle
);
4467 search_count_func(UNUSED_ARG(struct userNode
*source
), UNUSED_ARG(struct handle_info
*match
))
4472 search_unregister_func (struct userNode
*source
, struct handle_info
*match
)
4474 if (oper_has_access(source
, nickserv
, match
->opserv_level
, 0))
4475 nickserv_unregister_handle(match
, source
, nickserv
); // XXX nickserv hard coded
4480 search_add2ldap_func (struct userNode
*source
, struct handle_info
*match
)
4483 if(match
->email_addr
&& match
->passwd
&& match
->handle
) {
4484 rc
= ldap_do_add(match
->handle
, match
->passwd
, match
->email_addr
);
4485 if(rc
!= LDAP_SUCCESS
) {
4486 send_message(source
, nickserv
, "NSMSG_LDAP_FAIL_ADD", match
->handle
, ldap_err2string(rc
));
4493 nickserv_sort_accounts_by_access(const void *a
, const void *b
)
4495 const struct handle_info
*hi_a
= *(const struct handle_info
**)a
;
4496 const struct handle_info
*hi_b
= *(const struct handle_info
**)b
;
4497 if (hi_a
->opserv_level
!= hi_b
->opserv_level
)
4498 return hi_b
->opserv_level
- hi_a
->opserv_level
;
4499 return irccasecmp(hi_a
->handle
, hi_b
->handle
);
4503 nickserv_show_oper_accounts(struct userNode
*user
, struct svccmd
*cmd
)
4505 struct handle_info_list hil
;
4506 struct helpfile_table tbl
;
4511 memset(&hil
, 0, sizeof(hil
));
4512 for (it
= dict_first(nickserv_handle_dict
); it
; it
= iter_next(it
)) {
4513 struct handle_info
*hi
= iter_data(it
);
4514 if (hi
->opserv_level
)
4515 handle_info_list_append(&hil
, hi
);
4517 qsort(hil
.list
, hil
.used
, sizeof(hil
.list
[0]), nickserv_sort_accounts_by_access
);
4518 tbl
.length
= hil
.used
+ 1;
4520 tbl
.flags
= TABLE_NO_FREE
| TABLE_REPEAT_ROWS
| TABLE_REPEAT_HEADERS
;
4521 tbl
.contents
= malloc(tbl
.length
* sizeof(tbl
.contents
[0]));
4522 tbl
.contents
[0] = ary
= malloc(tbl
.width
* sizeof(ary
[0]));
4525 for (ii
= 0; ii
< hil
.used
; ) {
4526 ary
= malloc(tbl
.width
* sizeof(ary
[0]));
4527 ary
[0] = hil
.list
[ii
]->handle
;
4528 ary
[1] = strtab(hil
.list
[ii
]->opserv_level
);
4529 tbl
.contents
[++ii
] = ary
;
4531 table_send(cmd
->parent
->bot
, user
->nick
, 0, NULL
, tbl
);
4532 /*reply("MSG_MATCH_COUNT", hil.used); */
4533 for (ii
= 0; ii
< hil
.used
; ii
++)
4534 free(tbl
.contents
[ii
]);
4539 static NICKSERV_FUNC(cmd_search
)
4541 struct nickserv_discrim
*discrim
;
4542 discrim_search_func action
;
4543 struct svccmd
*subcmd
;
4544 unsigned int matches
;
4547 NICKSERV_MIN_PARMS(3);
4548 sprintf(buf
, "search %s", argv
[1]);
4549 subcmd
= dict_find(nickserv_service
->commands
, buf
, NULL
);
4550 if (!irccasecmp(argv
[1], "print"))
4551 action
= search_print_func
;
4552 else if (!irccasecmp(argv
[1], "count"))
4553 action
= search_count_func
;
4554 else if (!irccasecmp(argv
[1], "unregister"))
4555 action
= search_unregister_func
;
4557 else if (nickserv_conf
.ldap_enable
&& !irccasecmp(argv
[1], "add2ldap"))
4558 action
= search_add2ldap_func
;
4561 reply("NSMSG_INVALID_ACTION", argv
[1]);
4565 if (subcmd
&& !svccmd_can_invoke(user
, nickserv
, subcmd
, NULL
, SVCCMD_NOISY
))
4568 discrim
= nickserv_discrim_create(cmd
, user
, argc
-2, argv
+2);
4572 if (action
== search_print_func
)
4573 reply("NSMSG_ACCOUNT_SEARCH_RESULTS");
4574 else if (action
== search_count_func
)
4575 discrim
->limit
= INT_MAX
;
4577 matches
= nickserv_discrim_search(discrim
, action
, user
);
4580 reply("MSG_MATCH_COUNT", matches
);
4582 reply("MSG_NO_MATCHES");
4588 static MODCMD_FUNC(cmd_checkpass
)
4590 struct handle_info
*hi
;
4592 NICKSERV_MIN_PARMS(3);
4593 if (!(hi
= get_handle_info(argv
[1]))) {
4594 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
4597 if (checkpass(argv
[2], hi
->passwd
))
4598 reply("CHECKPASS_YES");
4600 reply("CHECKPASS_NO");
4605 static MODCMD_FUNC(cmd_checkemail
)
4607 struct handle_info
*hi
;
4609 NICKSERV_MIN_PARMS(3);
4610 if (!(hi
= modcmd_get_handle_info(user
, argv
[1]))) {
4613 if (!hi
->email_addr
)
4614 reply("CHECKEMAIL_NOT_SET");
4615 else if (!irccasecmp(argv
[2], hi
->email_addr
))
4616 reply("CHECKEMAIL_YES");
4618 reply("CHECKEMAIL_NO");
4623 nickserv_db_read_handle(char *handle
, dict_t obj
)
4626 struct string_list
*masks
, *sslfps
, *slist
, *ignores
;
4627 struct handle_info
*hi
;
4628 struct userNode
*authed_users
;
4629 struct userData
*channel_list
;
4630 unsigned long int id
;
4633 char *setter
, *note
;
4636 str
= database_get_data(obj
, KEY_ID
, RECDB_QSTRING
);
4637 id
= str
? strtoul(str
, NULL
, 0) : 0;
4638 str
= database_get_data(obj
, KEY_PASSWD
, RECDB_QSTRING
);
4640 log_module(NS_LOG
, LOG_WARNING
, "did not find a password for %s -- skipping user.", handle
);
4643 if ((hi
= get_handle_info(handle
))) {
4644 authed_users
= hi
->users
;
4645 channel_list
= hi
->channels
;
4647 hi
->channels
= NULL
;
4648 dict_remove(nickserv_handle_dict
, hi
->handle
);
4650 authed_users
= NULL
;
4651 channel_list
= NULL
;
4653 if(nickserv_conf
.force_handles_lowercase
)
4654 irc_strtolower(handle
);
4655 hi
= register_handle(handle
, str
, id
);
4657 hi
->users
= authed_users
;
4658 while (authed_users
) {
4659 authed_users
->handle_info
= hi
;
4660 authed_users
= authed_users
->next_authed
;
4663 hi
->channels
= channel_list
;
4664 masks
= database_get_data(obj
, KEY_MASKS
, RECDB_STRING_LIST
);
4665 hi
->masks
= masks
? string_list_copy(masks
) : alloc_string_list(1);
4666 sslfps
= database_get_data(obj
, KEY_SSLFPS
, RECDB_STRING_LIST
);
4667 hi
->sslfps
= sslfps
? string_list_copy(sslfps
) : alloc_string_list(1);
4668 ignores
= database_get_data(obj
, KEY_IGNORES
, RECDB_STRING_LIST
);
4669 hi
->ignores
= ignores
? string_list_copy(ignores
) : alloc_string_list(1);
4670 str
= database_get_data(obj
, KEY_MAXLOGINS
, RECDB_QSTRING
);
4671 hi
->maxlogins
= str
? strtoul(str
, NULL
, 0) : 0;
4672 str
= database_get_data(obj
, KEY_LANGUAGE
, RECDB_QSTRING
);
4673 hi
->language
= language_find(str
? str
: "C");
4674 str
= database_get_data(obj
, KEY_OPSERV_LEVEL
, RECDB_QSTRING
);
4675 hi
->opserv_level
= str
? strtoul(str
, NULL
, 0) : 0;
4676 str
= database_get_data(obj
, KEY_INFO
, RECDB_QSTRING
);
4678 hi
->infoline
= strdup(str
);
4679 str
= database_get_data(obj
, KEY_REGISTER_ON
, RECDB_QSTRING
);
4680 hi
->registered
= str
? (time_t)strtoul(str
, NULL
, 0) : now
;
4681 str
= database_get_data(obj
, KEY_LAST_SEEN
, RECDB_QSTRING
);
4682 hi
->lastseen
= str
? (time_t)strtoul(str
, NULL
, 0) : hi
->registered
;
4683 str
= database_get_data(obj
, KEY_KARMA
, RECDB_QSTRING
);
4684 hi
->karma
= str
? strtoul(str
, NULL
, 0) : 0;
4685 /* We want to read the nicks even if disable_nicks is set. This is so
4686 * that we don't lose the nick data entirely. */
4687 slist
= database_get_data(obj
, KEY_NICKS
, RECDB_STRING_LIST
);
4689 for (ii
=0; ii
<slist
->used
; ii
++)
4690 register_nick(slist
->list
[ii
], hi
);
4692 str
= database_get_data(obj
, KEY_FLAGS
, RECDB_QSTRING
);
4694 for (ii
=0; str
[ii
]; ii
++)
4695 hi
->flags
|= 1 << (handle_inverse_flags
[(unsigned char)str
[ii
]] - 1);
4697 str
= database_get_data(obj
, KEY_USERLIST_STYLE
, RECDB_QSTRING
);
4698 hi
->userlist_style
= str
? str
[0] : HI_DEFAULT_STYLE
;
4699 str
= database_get_data(obj
, KEY_ANNOUNCEMENTS
, RECDB_QSTRING
);
4700 hi
->announcements
= str
? str
[0] : '?';
4701 str
= database_get_data(obj
, KEY_SCREEN_WIDTH
, RECDB_QSTRING
);
4702 hi
->screen_width
= str
? strtoul(str
, NULL
, 0) : 0;
4703 str
= database_get_data(obj
, KEY_TABLE_WIDTH
, RECDB_QSTRING
);
4704 hi
->table_width
= str
? strtoul(str
, NULL
, 0) : 0;
4705 str
= database_get_data(obj
, KEY_LAST_QUIT_HOST
, RECDB_QSTRING
);
4707 str
= database_get_data(obj
, KEY_LAST_AUTHED_HOST
, RECDB_QSTRING
);
4709 safestrncpy(hi
->last_quit_host
, str
, sizeof(hi
->last_quit_host
));
4710 str
= database_get_data(obj
, KEY_EMAIL_ADDR
, RECDB_QSTRING
);
4712 nickserv_set_email_addr(hi
, str
);
4713 str
= database_get_data(obj
, KEY_EPITHET
, RECDB_QSTRING
);
4715 hi
->epithet
= strdup(str
);
4716 subdb
= database_get_data(obj
, KEY_NOTE_NOTE
, RECDB_OBJECT
);
4718 setter
= database_get_data(subdb
, KEY_NOTE_SETTER
, RECDB_QSTRING
);
4719 str
= database_get_data(subdb
, KEY_NOTE_DATE
, RECDB_QSTRING
);
4720 date
= str
? (time_t)strtoul(str
, NULL
, 0) : now
;
4721 note
= database_get_data(subdb
, KEY_NOTE_NOTE
, RECDB_QSTRING
);
4722 if (setter
&& date
&& note
)
4724 if (!(hi
->note
= nickserv_add_note(setter
, date
, note
)))
4729 str
= database_get_data(obj
, KEY_FAKEHOST
, RECDB_QSTRING
);
4731 hi
->fakehost
= strdup(str
);
4733 subdb
= database_get_data(obj
, KEY_COOKIE
, RECDB_OBJECT
);
4735 const char *data
, *type
, *expires
, *cookie_str
;
4736 struct handle_cookie
*cookie
;
4738 cookie
= calloc(1, sizeof(*cookie
));
4739 type
= database_get_data(subdb
, KEY_COOKIE_TYPE
, RECDB_QSTRING
);
4740 data
= database_get_data(subdb
, KEY_COOKIE_DATA
, RECDB_QSTRING
);
4741 expires
= database_get_data(subdb
, KEY_COOKIE_EXPIRES
, RECDB_QSTRING
);
4742 cookie_str
= database_get_data(subdb
, KEY_COOKIE
, RECDB_QSTRING
);
4743 if (!type
|| !expires
|| !cookie_str
) {
4744 log_module(NS_LOG
, LOG_ERROR
, "Missing field(s) from cookie for account %s; dropping cookie.", hi
->handle
);
4747 if (!irccasecmp(type
, KEY_ACTIVATION
))
4748 cookie
->type
= ACTIVATION
;
4749 else if (!irccasecmp(type
, KEY_PASSWORD_CHANGE
))
4750 cookie
->type
= PASSWORD_CHANGE
;
4751 else if (!irccasecmp(type
, KEY_EMAIL_CHANGE
))
4752 cookie
->type
= EMAIL_CHANGE
;
4753 else if (!irccasecmp(type
, KEY_ALLOWAUTH
))
4754 cookie
->type
= ALLOWAUTH
;
4756 log_module(NS_LOG
, LOG_ERROR
, "Invalid cookie type %s for account %s; dropping cookie.", type
, handle
);
4759 cookie
->expires
= strtoul(expires
, NULL
, 0);
4760 if (cookie
->expires
< now
)
4763 cookie
->data
= strdup(data
);
4764 safestrncpy(cookie
->cookie
, cookie_str
, sizeof(cookie
->cookie
));
4768 nickserv_bake_cookie(cookie
);
4770 nickserv_free_cookie(cookie
);
4775 nickserv_saxdb_read(dict_t db
) {
4777 struct record_data
*rd
;
4780 for (it
=dict_first(db
); it
; it
=iter_next(it
)) {
4782 handle
= strdup(iter_key(it
));
4783 nickserv_db_read_handle(handle
, rd
->d
.object
);
4789 static NICKSERV_FUNC(cmd_mergedb
)
4791 struct timeval start
, stop
;
4794 NICKSERV_MIN_PARMS(2);
4795 gettimeofday(&start
, NULL
);
4796 if (!(db
= parse_database(argv
[1]))) {
4797 reply("NSMSG_DB_UNREADABLE", argv
[1]);
4800 nickserv_saxdb_read(db
);
4802 gettimeofday(&stop
, NULL
);
4803 stop
.tv_sec
-= start
.tv_sec
;
4804 stop
.tv_usec
-= start
.tv_usec
;
4805 if (stop
.tv_usec
< 0) {
4807 stop
.tv_usec
+= 1000000;
4809 reply("NSMSG_DB_MERGED", argv
[1], stop
.tv_sec
, stop
.tv_usec
/1000);
4814 expire_handles(UNUSED_ARG(void *data
))
4816 dict_iterator_t it
, next
;
4818 struct handle_info
*hi
;
4820 for (it
=dict_first(nickserv_handle_dict
); it
; it
=next
) {
4821 next
= iter_next(it
);
4823 if ((hi
->opserv_level
> 0)
4825 || HANDLE_FLAGGED(hi
, FROZEN
)
4826 || HANDLE_FLAGGED(hi
, NODELETE
)) {
4829 expiry
= hi
->channels
? nickserv_conf
.handle_expire_delay
: nickserv_conf
.nochan_handle_expire_delay
;
4830 if ((now
- hi
->lastseen
) > expiry
) {
4831 log_module(NS_LOG
, LOG_INFO
, "Expiring account %s for inactivity.", hi
->handle
);
4832 nickserv_unregister_handle(hi
, NULL
, NULL
);
4836 if (nickserv_conf
.handle_expire_frequency
)
4837 timeq_add(now
+ nickserv_conf
.handle_expire_frequency
, expire_handles
, NULL
);
4841 nickserv_load_dict(const char *fname
)
4845 if (!(file
= fopen(fname
, "r"))) {
4846 log_module(NS_LOG
, LOG_ERROR
, "Unable to open dictionary file %s: %s", fname
, strerror(errno
));
4849 while (fgets(line
, sizeof(line
), file
)) {
4852 if (line
[strlen(line
)-1] == '\n')
4853 line
[strlen(line
)-1] = 0;
4854 dict_insert(nickserv_conf
.weak_password_dict
, strdup(line
), NULL
);
4857 log_module(NS_LOG
, LOG_INFO
, "Loaded %d words into weak password dictionary.", dict_size(nickserv_conf
.weak_password_dict
));
4860 static enum reclaim_action
4861 reclaim_action_from_string(const char *str
) {
4863 return RECLAIM_NONE
;
4864 else if (!irccasecmp(str
, "warn"))
4865 return RECLAIM_WARN
;
4866 else if (!irccasecmp(str
, "svsnick"))
4867 return RECLAIM_SVSNICK
;
4868 else if (!irccasecmp(str
, "kill"))
4869 return RECLAIM_KILL
;
4871 return RECLAIM_NONE
;
4875 nickserv_conf_read(void)
4877 dict_t conf_node
, child
;
4880 struct string_list
*strlist
;
4882 if (!(conf_node
= conf_get_data(NICKSERV_CONF_NAME
, RECDB_OBJECT
))) {
4883 log_module(NS_LOG
, LOG_ERROR
, "config node `%s' is missing or has wrong type.", NICKSERV_CONF_NAME
);
4886 str
= database_get_data(conf_node
, KEY_VALID_HANDLE_REGEX
, RECDB_QSTRING
);
4888 str
= database_get_data(conf_node
, KEY_VALID_ACCOUNT_REGEX
, RECDB_QSTRING
);
4889 if (nickserv_conf
.valid_handle_regex_set
)
4890 regfree(&nickserv_conf
.valid_handle_regex
);
4892 int err
= regcomp(&nickserv_conf
.valid_handle_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
4893 nickserv_conf
.valid_handle_regex_set
= !err
;
4894 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_account_regex (error %d)", err
);
4896 nickserv_conf
.valid_handle_regex_set
= 0;
4898 str
= database_get_data(conf_node
, KEY_VALID_NICK_REGEX
, RECDB_QSTRING
);
4899 if (nickserv_conf
.valid_nick_regex_set
)
4900 regfree(&nickserv_conf
.valid_nick_regex
);
4902 int err
= regcomp(&nickserv_conf
.valid_nick_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
4903 nickserv_conf
.valid_nick_regex_set
= !err
;
4904 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_nick_regex (error %d)", err
);
4906 nickserv_conf
.valid_nick_regex_set
= 0;
4908 str
= database_get_data(conf_node
, KEY_VALID_FAKEHOST_REGEX
, RECDB_QSTRING
);
4909 if (nickserv_conf
.valid_fakehost_regex_set
)
4910 regfree(&nickserv_conf
.valid_fakehost_regex
);
4912 int err
= regcomp(&nickserv_conf
.valid_fakehost_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
4913 nickserv_conf
.valid_fakehost_regex_set
= !err
;
4914 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_fakehost_regex (error %d)", err
);
4916 nickserv_conf
.valid_fakehost_regex_set
= 0;
4918 str
= database_get_data(conf_node
, KEY_NICKS_PER_HANDLE
, RECDB_QSTRING
);
4920 str
= database_get_data(conf_node
, KEY_NICKS_PER_ACCOUNT
, RECDB_QSTRING
);
4921 nickserv_conf
.nicks_per_handle
= str
? strtoul(str
, NULL
, 0) : 4;
4922 str
= database_get_data(conf_node
, KEY_DISABLE_NICKS
, RECDB_QSTRING
);
4923 nickserv_conf
.disable_nicks
= str
? strtoul(str
, NULL
, 0) : 0;
4924 str
= database_get_data(conf_node
, KEY_DEFAULT_HOSTMASK
, RECDB_QSTRING
);
4925 nickserv_conf
.default_hostmask
= str
? !disabled_string(str
) : 0;
4926 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_LENGTH
, RECDB_QSTRING
);
4927 nickserv_conf
.password_min_length
= str
? strtoul(str
, NULL
, 0) : 0;
4928 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_DIGITS
, RECDB_QSTRING
);
4929 nickserv_conf
.password_min_digits
= str
? strtoul(str
, NULL
, 0) : 0;
4930 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_UPPER
, RECDB_QSTRING
);
4931 nickserv_conf
.password_min_upper
= str
? strtoul(str
, NULL
, 0) : 0;
4932 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_LOWER
, RECDB_QSTRING
);
4933 nickserv_conf
.password_min_lower
= str
? strtoul(str
, NULL
, 0) : 0;
4934 str
= database_get_data(conf_node
, KEY_DB_BACKUP_FREQ
, RECDB_QSTRING
);
4935 nickserv_conf
.db_backup_frequency
= str
? ParseInterval(str
) : 7200;
4936 str
= database_get_data(conf_node
, KEY_MODOPER_LEVEL
, RECDB_QSTRING
);
4937 nickserv_conf
.modoper_level
= str
? strtoul(str
, NULL
, 0) : 900;
4938 str
= database_get_data(conf_node
, KEY_SET_EPITHET_LEVEL
, RECDB_QSTRING
);
4939 nickserv_conf
.set_epithet_level
= str
? strtoul(str
, NULL
, 0) : 1;
4940 str
= database_get_data(conf_node
, KEY_SET_TITLE_LEVEL
, RECDB_QSTRING
);
4941 nickserv_conf
.set_title_level
= str
? strtoul(str
, NULL
, 0) : 900;
4942 str
= database_get_data(conf_node
, KEY_SET_FAKEHOST_LEVEL
, RECDB_QSTRING
);
4943 nickserv_conf
.set_fakehost_level
= str
? strtoul(str
, NULL
, 0) : 1000;
4944 str
= database_get_data(conf_node
, KEY_HANDLE_EXPIRE_FREQ
, RECDB_QSTRING
);
4946 str
= database_get_data(conf_node
, KEY_ACCOUNT_EXPIRE_FREQ
, RECDB_QSTRING
);
4947 nickserv_conf
.handle_expire_frequency
= str
? ParseInterval(str
) : 86400;
4948 str
= database_get_data(conf_node
, KEY_HANDLE_EXPIRE_DELAY
, RECDB_QSTRING
);
4950 str
= database_get_data(conf_node
, KEY_ACCOUNT_EXPIRE_DELAY
, RECDB_QSTRING
);
4951 nickserv_conf
.handle_expire_delay
= str
? ParseInterval(str
) : 86400*30;
4952 str
= database_get_data(conf_node
, KEY_NOCHAN_HANDLE_EXPIRE_DELAY
, RECDB_QSTRING
);
4954 str
= database_get_data(conf_node
, KEY_NOCHAN_ACCOUNT_EXPIRE_DELAY
, RECDB_QSTRING
);
4955 nickserv_conf
.nochan_handle_expire_delay
= str
? ParseInterval(str
) : 86400*15;
4956 str
= database_get_data(conf_node
, "warn_clone_auth", RECDB_QSTRING
);
4957 nickserv_conf
.warn_clone_auth
= str
? !disabled_string(str
) : 1;
4958 str
= database_get_data(conf_node
, "default_maxlogins", RECDB_QSTRING
);
4959 nickserv_conf
.default_maxlogins
= str
? strtoul(str
, NULL
, 0) : 2;
4960 str
= database_get_data(conf_node
, "hard_maxlogins", RECDB_QSTRING
);
4961 str
= database_get_data(conf_node
, KEY_OUNREGISTER_INACTIVE
, RECDB_QSTRING
);
4962 nickserv_conf
.ounregister_inactive
= str
? ParseInterval(str
) : 86400*28;
4963 str
= database_get_data(conf_node
, KEY_OUNREGISTER_FLAGS
, RECDB_QSTRING
);
4966 nickserv_conf
.ounregister_flags
= 0;
4968 unsigned int pos
= handle_inverse_flags
[(unsigned char)*str
];
4971 nickserv_conf
.ounregister_flags
|= 1 << (pos
- 1);
4973 nickserv_conf
.hard_maxlogins
= str
? strtoul(str
, NULL
, 0) : 10;
4974 if (!nickserv_conf
.disable_nicks
) {
4975 str
= database_get_data(conf_node
, "reclaim_action", RECDB_QSTRING
);
4976 nickserv_conf
.reclaim_action
= str
? reclaim_action_from_string(str
) : RECLAIM_NONE
;
4977 str
= database_get_data(conf_node
, "warn_nick_owned", RECDB_QSTRING
);
4978 nickserv_conf
.warn_nick_owned
= str
? enabled_string(str
) : 0;
4979 str
= database_get_data(conf_node
, "auto_reclaim_action", RECDB_QSTRING
);
4980 nickserv_conf
.auto_reclaim_action
= str
? reclaim_action_from_string(str
) : RECLAIM_NONE
;
4981 str
= database_get_data(conf_node
, "auto_reclaim_delay", RECDB_QSTRING
);
4982 nickserv_conf
.auto_reclaim_delay
= str
? ParseInterval(str
) : 0;
4984 child
= database_get_data(conf_node
, KEY_FLAG_LEVELS
, RECDB_OBJECT
);
4985 for (it
=dict_first(child
); it
; it
=iter_next(it
)) {
4986 const char *key
= iter_key(it
), *value
;
4990 if (!strncasecmp(key
, "uc_", 3))
4991 flag
= toupper(key
[3]);
4992 else if (!strncasecmp(key
, "lc_", 3))
4993 flag
= tolower(key
[3]);
4997 if ((pos
= handle_inverse_flags
[flag
])) {
4998 value
= GET_RECORD_QSTRING((struct record_data
*)iter_data(it
));
4999 flag_access_levels
[pos
- 1] = strtoul(value
, NULL
, 0);
5002 if (nickserv_conf
.weak_password_dict
)
5003 dict_delete(nickserv_conf
.weak_password_dict
);
5004 nickserv_conf
.weak_password_dict
= dict_new();
5005 dict_set_free_keys(nickserv_conf
.weak_password_dict
, free
);
5006 dict_insert(nickserv_conf
.weak_password_dict
, strdup("password"), NULL
);
5007 dict_insert(nickserv_conf
.weak_password_dict
, strdup("<password>"), NULL
);
5008 str
= database_get_data(conf_node
, KEY_DICT_FILE
, RECDB_QSTRING
);
5010 nickserv_load_dict(str
);
5011 str
= database_get_data(conf_node
, KEY_NICK
, RECDB_QSTRING
);
5012 if (nickserv
&& str
)
5013 NickChange(nickserv
, str
, 0);
5014 str
= database_get_data(conf_node
, KEY_AUTOGAG_ENABLED
, RECDB_QSTRING
);
5015 nickserv_conf
.autogag_enabled
= str
? strtoul(str
, NULL
, 0) : 1;
5016 str
= database_get_data(conf_node
, KEY_AUTOGAG_DURATION
, RECDB_QSTRING
);
5017 nickserv_conf
.autogag_duration
= str
? ParseInterval(str
) : 1800;
5018 str
= database_get_data(conf_node
, KEY_EMAIL_VISIBLE_LEVEL
, RECDB_QSTRING
);
5019 nickserv_conf
.email_visible_level
= str
? strtoul(str
, NULL
, 0) : 800;
5020 str
= database_get_data(conf_node
, KEY_EMAIL_ENABLED
, RECDB_QSTRING
);
5021 nickserv_conf
.email_enabled
= str
? enabled_string(str
) : 0;
5022 str
= database_get_data(conf_node
, KEY_SYNC_LOG
, RECDB_QSTRING
);
5023 nickserv_conf
.sync_log
= str
? enabled_string(str
) : 0;
5024 str
= database_get_data(conf_node
, KEY_COOKIE_TIMEOUT
, RECDB_QSTRING
);
5025 nickserv_conf
.cookie_timeout
= str
? ParseInterval(str
) : 24*3600;
5026 str
= database_get_data(conf_node
, KEY_EMAIL_REQUIRED
, RECDB_QSTRING
);
5027 nickserv_conf
.email_required
= (nickserv_conf
.email_enabled
&& str
) ? enabled_string(str
) : 0;
5028 str
= database_get_data(conf_node
, KEY_ACCOUNTS_PER_EMAIL
, RECDB_QSTRING
);
5029 nickserv_conf
.handles_per_email
= str
? strtoul(str
, NULL
, 0) : 1;
5030 str
= database_get_data(conf_node
, KEY_EMAIL_SEARCH_LEVEL
, RECDB_QSTRING
);
5031 nickserv_conf
.email_search_level
= str
? strtoul(str
, NULL
, 0) : 600;
5032 str
= database_get_data(conf_node
, KEY_TITLEHOST_SUFFIX
, RECDB_QSTRING
);
5033 nickserv_conf
.titlehost_suffix
= str
? str
: "example.net";
5035 free_string_list(nickserv_conf
.denied_fakehost_words
);
5036 strlist
= database_get_data(conf_node
, KEY_DENIED_FAKEHOST_WORDS
, RECDB_STRING_LIST
);
5038 strlist
= string_list_copy(strlist
);
5040 strlist
= alloc_string_list(4);
5041 string_list_append(strlist
, strdup("sex"));
5042 string_list_append(strlist
, strdup("fuck"));
5044 nickserv_conf
.denied_fakehost_words
= strlist
;
5046 str
= database_get_data(conf_node
, KEY_DEFAULT_STYLE
, RECDB_QSTRING
);
5047 nickserv_conf
.default_style
= str
? str
[0] : HI_DEFAULT_STYLE
;
5049 str
= database_get_data(conf_node
, KEY_AUTO_OPER
, RECDB_QSTRING
);
5050 nickserv_conf
.auto_oper
= str
? str
: "";
5052 str
= database_get_data(conf_node
, KEY_AUTO_ADMIN
, RECDB_QSTRING
);
5053 nickserv_conf
.auto_admin
= str
? str
: "";
5055 str
= database_get_data(conf_node
, KEY_AUTO_OPER_PRIVS
, RECDB_QSTRING
);
5056 nickserv_conf
.auto_oper_privs
= str
? str
: "";
5058 str
= database_get_data(conf_node
, KEY_AUTO_ADMIN_PRIVS
, RECDB_QSTRING
);
5059 nickserv_conf
.auto_admin_privs
= str
? str
: "";
5061 str
= conf_get_data("server/network", RECDB_QSTRING
);
5062 nickserv_conf
.network_name
= str
? str
: "some IRC network";
5063 if (!nickserv_conf
.auth_policer_params
) {
5064 nickserv_conf
.auth_policer_params
= policer_params_new();
5065 policer_params_set(nickserv_conf
.auth_policer_params
, "size", "5");
5066 policer_params_set(nickserv_conf
.auth_policer_params
, "drain-rate", "0.05");
5068 child
= database_get_data(conf_node
, KEY_AUTH_POLICER
, RECDB_OBJECT
);
5069 for (it
=dict_first(child
); it
; it
=iter_next(it
))
5070 set_policer_param(iter_key(it
), iter_data(it
), nickserv_conf
.auth_policer_params
);
5072 str
= database_get_data(conf_node
, KEY_LDAP_ENABLE
, RECDB_QSTRING
);
5073 nickserv_conf
.ldap_enable
= str
? strtoul(str
, NULL
, 0) : 0;
5075 str
= database_get_data(conf_node
, KEY_FORCE_HANDLES_LOWERCASE
, RECDB_QSTRING
);
5076 nickserv_conf
.force_handles_lowercase
= str
? strtol(str
, NULL
, 0) : 0;
5079 if(nickserv_conf
.ldap_enable
> 0) {
5080 /* ldap is enabled but not compiled in - error out */
5081 log_module(MAIN_LOG
, LOG_ERROR
, "ldap is enabled in config, but not compiled in!");
5082 nickserv_conf
.ldap_enable
= 0;
5088 str
= database_get_data(conf_node
, KEY_LDAP_URI
, RECDB_QSTRING
);
5089 nickserv_conf
.ldap_uri
= str
? str
: "";
5091 str
= database_get_data(conf_node
, KEY_LDAP_BASE
, RECDB_QSTRING
);
5092 nickserv_conf
.ldap_base
= str
? str
: "";
5094 str
= database_get_data(conf_node
, KEY_LDAP_DN_FMT
, RECDB_QSTRING
);
5095 nickserv_conf
.ldap_dn_fmt
= str
? str
: "";
5097 str
= database_get_data(conf_node
, KEY_LDAP_VERSION
, RECDB_QSTRING
);
5098 nickserv_conf
.ldap_version
= str
? strtoul(str
, NULL
, 0) : 3;
5100 str
= database_get_data(conf_node
, KEY_LDAP_AUTOCREATE
, RECDB_QSTRING
);
5101 nickserv_conf
.ldap_autocreate
= str
? strtoul(str
, NULL
, 0) : 0;
5103 str
= database_get_data(conf_node
, KEY_LDAP_TIMEOUT
, RECDB_QSTRING
);
5104 nickserv_conf
.ldap_timeout
= str
? strtoul(str
, NULL
, 0) : 5;
5106 str
= database_get_data(conf_node
, KEY_LDAP_ADMIN_DN
, RECDB_QSTRING
);
5107 nickserv_conf
.ldap_admin_dn
= str
? str
: "";
5109 str
= database_get_data(conf_node
, KEY_LDAP_ADMIN_PASS
, RECDB_QSTRING
);
5110 nickserv_conf
.ldap_admin_pass
= str
? str
: "";
5112 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_ACCOUNT
, RECDB_QSTRING
);
5113 nickserv_conf
.ldap_field_account
= str
? str
: "";
5115 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_PASSWORD
, RECDB_QSTRING
);
5116 nickserv_conf
.ldap_field_password
= str
? str
: "";
5118 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_EMAIL
, RECDB_QSTRING
);
5119 nickserv_conf
.ldap_field_email
= str
? str
: "";
5121 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_OSLEVEL
, RECDB_QSTRING
);
5122 nickserv_conf
.ldap_field_oslevel
= str
? str
: "";
5124 str
= database_get_data(conf_node
, KEY_LDAP_OPER_GROUP_DN
, RECDB_QSTRING
);
5125 nickserv_conf
.ldap_oper_group_dn
= str
? str
: "";
5127 str
= database_get_data(conf_node
, KEY_LDAP_OPER_GROUP_LEVEL
, RECDB_QSTRING
);
5128 nickserv_conf
.ldap_oper_group_level
= str
? strtoul(str
, NULL
, 0) : 99;
5130 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_GROUP_MEMBER
, RECDB_QSTRING
);
5131 nickserv_conf
.ldap_field_group_member
= str
? str
: "";
5133 free_string_list(nickserv_conf
.ldap_object_classes
);
5134 strlist
= database_get_data(conf_node
, KEY_LDAP_OBJECT_CLASSES
, RECDB_STRING_LIST
);
5136 strlist
= string_list_copy(strlist
);
5138 strlist
= alloc_string_list(4);
5139 string_list_append(strlist
, strdup("top"));
5141 nickserv_conf
.ldap_object_classes
= strlist
;
5148 nickserv_reclaim(struct userNode
*user
, struct nick_info
*ni
, enum reclaim_action action
) {
5150 char newnick
[NICKLEN
+1];
5159 send_message(user
, nickserv
, "NSMSG_RECLAIM_WARN", ni
->nick
, ni
->owner
->handle
);
5160 send_message(user
, nickserv
, "NSMSG_RECLAIM_HOWTO", ni
->owner
->handle
, nickserv
->nick
, self
->name
, ni
->owner
->handle
);
5162 case RECLAIM_SVSNICK
:
5164 snprintf(newnick
, sizeof(newnick
), "Guest%d", rand()%10000
);
5165 } while (GetUserH(newnick
));
5166 irc_svsnick(nickserv
, user
, newnick
);
5169 msg
= user_find_message(user
, "NSMSG_RECLAIM_KILL");
5170 DelUser(user
, nickserv
, 1, msg
);
5176 nickserv_reclaim_p(void *data
) {
5177 struct userNode
*user
= data
;
5178 struct nick_info
*ni
= get_nick_info(user
->nick
);
5180 nickserv_reclaim(user
, ni
, nickserv_conf
.auto_reclaim_action
);
5184 check_user_nick(struct userNode
*user
, UNUSED_ARG(void *extra
)) {
5185 struct nick_info
*ni
;
5186 user
->modes
&= ~FLAGS_REGNICK
;
5187 if (!(ni
= get_nick_info(user
->nick
)))
5189 if (user
->handle_info
== ni
->owner
) {
5190 user
->modes
|= FLAGS_REGNICK
;
5194 if (nickserv_conf
.warn_nick_owned
)
5195 send_message(user
, nickserv
, "NSMSG_RECLAIM_WARN", ni
->nick
, ni
->owner
->handle
);
5196 send_message(user
, nickserv
, "NSMSG_RECLAIM_HOWTO", ni
->owner
->handle
, nickserv
->nick
, self
->name
, ni
->owner
->handle
);
5197 if (nickserv_conf
.auto_reclaim_action
== RECLAIM_NONE
)
5199 if (nickserv_conf
.auto_reclaim_delay
)
5200 timeq_add(now
+ nickserv_conf
.auto_reclaim_delay
, nickserv_reclaim_p
, user
);
5202 nickserv_reclaim(user
, ni
, nickserv_conf
.auto_reclaim_action
);
5208 handle_account(struct userNode
*user
, const char *stamp
)
5210 struct handle_info
*hi
;
5213 #ifdef WITH_PROTOCOL_P10
5214 time_t timestamp
= 0;
5216 colon
= strchr(stamp
, ':');
5217 if(colon
&& colon
[1])
5220 timestamp
= atoi(colon
+1);
5222 hi
= dict_find(nickserv_handle_dict
, stamp
, NULL
);
5223 if(hi
&& timestamp
&& hi
->registered
!= timestamp
)
5225 log_module(MAIN_LOG
, LOG_WARNING
, "%s using account %s but timestamp does not match %s is not %s.", user
->nick
, stamp
, ctime(×tamp
),
5226 ctime(&hi
->registered
));
5230 hi
= dict_find(nickserv_id_dict
, stamp
, NULL
);
5231 log_module(MAIN_LOG
, LOG_WARNING
, "Using non-P10 code in accounts, not tested at all!");
5235 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
5238 set_user_handle_info(user
, hi
, 0);
5240 log_module(MAIN_LOG
, LOG_WARNING
, "%s had unknown account stamp %s.", user
->nick
, stamp
);
5245 handle_nick_change(struct userNode
*user
, const char *old_nick
, UNUSED_ARG(void *extra
))
5247 struct handle_info
*hi
;
5249 if ((hi
= dict_find(nickserv_allow_auth_dict
, old_nick
, 0))) {
5250 dict_remove(nickserv_allow_auth_dict
, old_nick
);
5251 dict_insert(nickserv_allow_auth_dict
, user
->nick
, hi
);
5253 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
5254 check_user_nick(user
, NULL
);
5258 nickserv_remove_user(struct userNode
*user
, UNUSED_ARG(struct userNode
*killer
), UNUSED_ARG(const char *why
), UNUSED_ARG(void *extra
))
5260 dict_remove(nickserv_allow_auth_dict
, user
->nick
);
5261 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
5262 set_user_handle_info(user
, NULL
, 0);
5265 static struct modcmd
*
5266 nickserv_define_func(const char *name
, modcmd_func_t func
, int min_level
, int must_auth
, int must_be_qualified
)
5268 if (min_level
> 0) {
5270 sprintf(buf
, "%u", min_level
);
5271 if (must_be_qualified
) {
5272 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "level", buf
, "flags", "+qualified,+loghostmask", NULL
);
5274 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "level", buf
, NULL
);
5276 } else if (min_level
== 0) {
5277 if (must_be_qualified
) {
5278 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+helping", NULL
);
5280 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+helping", NULL
);
5283 if (must_be_qualified
) {
5284 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+qualified,+loghostmask", NULL
);
5286 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), NULL
);
5292 nickserv_db_cleanup(UNUSED_ARG(void* extra
))
5294 unreg_del_user_func(nickserv_remove_user
, NULL
);
5295 userList_clean(&curr_helpers
);
5296 policer_params_delete(nickserv_conf
.auth_policer_params
);
5297 dict_delete(nickserv_handle_dict
);
5298 dict_delete(nickserv_nick_dict
);
5299 dict_delete(nickserv_opt_dict
);
5300 dict_delete(nickserv_allow_auth_dict
);
5301 dict_delete(nickserv_email_dict
);
5302 dict_delete(nickserv_id_dict
);
5303 dict_delete(nickserv_conf
.weak_password_dict
);
5304 free(auth_func_list
);
5305 free(auth_func_list_extra
);
5306 free(unreg_func_list
);
5307 free(unreg_func_list_extra
);
5309 free(rf_list_extra
);
5310 free(allowauth_func_list
);
5311 free(allowauth_func_list_extra
);
5312 free(handle_merge_func_list
);
5313 free(handle_merge_func_list_extra
);
5314 free(failpw_func_list
);
5315 free(failpw_func_list_extra
);
5316 if (nickserv_conf
.valid_handle_regex_set
)
5317 regfree(&nickserv_conf
.valid_handle_regex
);
5318 if (nickserv_conf
.valid_nick_regex_set
)
5319 regfree(&nickserv_conf
.valid_nick_regex
);
5322 void handle_loc_auth_oper(struct userNode
*user
, UNUSED_ARG(struct handle_info
*old_handle
), UNUSED_ARG(void *extra
)) {
5323 if (!*nickserv_conf
.auto_oper
|| !user
->handle_info
)
5326 if (!IsOper(user
)) {
5327 if (*nickserv_conf
.auto_admin
&& user
->handle_info
->opserv_level
>= opserv_conf_admin_level()) {
5328 irc_umode(user
, nickserv_conf
.auto_admin
);
5329 irc_sno(0x1, "%s (%s@%s) is now an IRC Administrator",
5330 user
->nick
, user
->ident
, user
->hostname
);
5331 } else if (*nickserv_conf
.auto_oper
&& user
->handle_info
->opserv_level
) {
5332 irc_umode(user
, nickserv_conf
.auto_oper
);
5333 irc_sno(0x1, "%s (%s@%s) is now an IRC Operator",
5334 user
->nick
, user
->ident
, user
->hostname
);
5340 init_nickserv(const char *nick
)
5342 struct chanNode
*chan
;
5344 NS_LOG
= log_register_type("NickServ", "file:nickserv.log");
5345 reg_new_user_func(check_user_nick
, NULL
);
5346 reg_nick_change_func(handle_nick_change
, NULL
);
5347 reg_del_user_func(nickserv_remove_user
, NULL
);
5348 reg_account_func(handle_account
);
5349 reg_auth_func(handle_loc_auth_oper
, NULL
);
5351 /* set up handle_inverse_flags */
5352 memset(handle_inverse_flags
, 0, sizeof(handle_inverse_flags
));
5353 for (i
=0; handle_flags
[i
]; i
++) {
5354 handle_inverse_flags
[(unsigned char)handle_flags
[i
]] = i
+ 1;
5355 flag_access_levels
[i
] = 0;
5358 conf_register_reload(nickserv_conf_read
);
5359 nickserv_opt_dict
= dict_new();
5360 nickserv_email_dict
= dict_new();
5362 dict_set_free_keys(nickserv_email_dict
, free
);
5363 dict_set_free_data(nickserv_email_dict
, nickserv_free_email_addr
);
5365 nickserv_module
= module_register("NickServ", NS_LOG
, "nickserv.help", NULL
);
5366 /* Removed qualified_host as default requirement for AUTH, REGISTER, PASS, etc. nets
5367 * can enable it per command using modcmd. (its a shitty default IMO, and now in 1.3
5368 * a big pain to disable since its nolonger in the config file. ) -Rubin
5370 modcmd_register(nickserv_module
, "AUTH", cmd_auth
, 2, MODCMD_KEEP_BOUND
, "flags", "+loghostmask", NULL
);
5371 nickserv_define_func("ALLOWAUTH", cmd_allowauth
, 0, 1, 0);
5372 nickserv_define_func("REGISTER", cmd_register
, -1, 0, 0);
5373 nickserv_define_func("OREGISTER", cmd_oregister
, 0, 1, 0);
5374 nickserv_define_func("UNREGISTER", cmd_unregister
, -1, 1, 0);
5375 nickserv_define_func("OUNREGISTER", cmd_ounregister
, 0, 1, 0);
5376 nickserv_define_func("ADDMASK", cmd_addmask
, -1, 1, 0);
5377 nickserv_define_func("OADDMASK", cmd_oaddmask
, 0, 1, 0);
5378 nickserv_define_func("DELMASK", cmd_delmask
, -1, 1, 0);
5379 nickserv_define_func("ODELMASK", cmd_odelmask
, 0, 1, 0);
5380 nickserv_define_func("ADDSSLFP", cmd_addsslfp
, -1, 1, 0);
5381 nickserv_define_func("OADDSSLFP", cmd_oaddsslfp
, 0, 1, 0);
5382 nickserv_define_func("DELSSLFP", cmd_delsslfp
, -1, 1, 0);
5383 nickserv_define_func("ODELSSLFP", cmd_odelsslfp
, 0, 1, 0);
5384 nickserv_define_func("PASS", cmd_pass
, -1, 1, 0);
5385 nickserv_define_func("SET", cmd_set
, -1, 1, 0);
5386 nickserv_define_func("OSET", cmd_oset
, 0, 1, 0);
5387 nickserv_define_func("ACCOUNTINFO", cmd_handleinfo
, -1, 0, 0);
5388 nickserv_define_func("USERINFO", cmd_userinfo
, -1, 1, 0);
5389 nickserv_define_func("RENAME", cmd_rename_handle
, -1, 1, 0);
5390 nickserv_define_func("VACATION", cmd_vacation
, -1, 1, 0);
5391 nickserv_define_func("MERGE", cmd_merge
, 750, 1, 0);
5392 if (!nickserv_conf
.disable_nicks
) {
5393 /* nick management commands */
5394 nickserv_define_func("REGNICK", cmd_regnick
, -1, 1, 0);
5395 nickserv_define_func("OREGNICK", cmd_oregnick
, 0, 1, 0);
5396 nickserv_define_func("UNREGNICK", cmd_unregnick
, -1, 1, 0);
5397 nickserv_define_func("OUNREGNICK", cmd_ounregnick
, 0, 1, 0);
5398 nickserv_define_func("NICKINFO", cmd_nickinfo
, -1, 1, 0);
5399 nickserv_define_func("RECLAIM", cmd_reclaim
, -1, 1, 0);
5401 if (nickserv_conf
.email_enabled
) {
5402 nickserv_define_func("AUTHCOOKIE", cmd_authcookie
, -1, 0, 0);
5403 nickserv_define_func("RESETPASS", cmd_resetpass
, -1, 0, 0);
5404 nickserv_define_func("COOKIE", cmd_cookie
, -1, 0, 0);
5405 nickserv_define_func("DELCOOKIE", cmd_delcookie
, -1, 1, 0);
5406 nickserv_define_func("ODELCOOKIE", cmd_odelcookie
, 0, 1, 0);
5407 dict_insert(nickserv_opt_dict
, "EMAIL", opt_email
);
5409 nickserv_define_func("GHOST", cmd_ghost
, -1, 1, 0);
5410 /* ignore commands */
5411 nickserv_define_func("ADDIGNORE", cmd_addignore
, -1, 1, 0);
5412 nickserv_define_func("OADDIGNORE", cmd_oaddignore
, 0, 1, 0);
5413 nickserv_define_func("DELIGNORE", cmd_delignore
, -1, 1, 0);
5414 nickserv_define_func("ODELIGNORE", cmd_odelignore
, 0, 1, 0);
5415 /* miscellaneous commands */
5416 nickserv_define_func("STATUS", cmd_status
, -1, 0, 0);
5417 nickserv_define_func("SEARCH", cmd_search
, 100, 1, 0);
5418 nickserv_define_func("SEARCH UNREGISTER", NULL
, 800, 1, 0);
5419 nickserv_define_func("MERGEDB", cmd_mergedb
, 999, 1, 0);
5420 nickserv_define_func("CHECKPASS", cmd_checkpass
, 601, 1, 0);
5421 nickserv_define_func("CHECKEMAIL", cmd_checkemail
, 0, 1, 0);
5423 dict_insert(nickserv_opt_dict
, "INFO", opt_info
);
5424 dict_insert(nickserv_opt_dict
, "WIDTH", opt_width
);
5425 dict_insert(nickserv_opt_dict
, "TABLEWIDTH", opt_tablewidth
);
5426 dict_insert(nickserv_opt_dict
, "COLOR", opt_color
);
5427 dict_insert(nickserv_opt_dict
, "PRIVMSG", opt_privmsg
);
5428 dict_insert(nickserv_opt_dict
, "AUTOHIDE", opt_autohide
);
5429 dict_insert(nickserv_opt_dict
, "STYLE", opt_style
);
5430 dict_insert(nickserv_opt_dict
, "PASS", opt_password
);
5431 dict_insert(nickserv_opt_dict
, "PASSWORD", opt_password
);
5432 dict_insert(nickserv_opt_dict
, "FLAGS", opt_flags
);
5433 dict_insert(nickserv_opt_dict
, "ACCESS", opt_level
);
5434 dict_insert(nickserv_opt_dict
, "LEVEL", opt_level
);
5435 dict_insert(nickserv_opt_dict
, "EPITHET", opt_epithet
);
5436 dict_insert(nickserv_opt_dict
, "NOTE", opt_note
);
5437 if (nickserv_conf
.titlehost_suffix
) {
5438 dict_insert(nickserv_opt_dict
, "TITLE", opt_title
);
5439 dict_insert(nickserv_opt_dict
, "FAKEHOST", opt_fakehost
);
5441 dict_insert(nickserv_opt_dict
, "ANNOUNCEMENTS", opt_announcements
);
5442 dict_insert(nickserv_opt_dict
, "MAXLOGINS", opt_maxlogins
);
5443 dict_insert(nickserv_opt_dict
, "ADVANCED", opt_advanced
);
5444 dict_insert(nickserv_opt_dict
, "LANGUAGE", opt_language
);
5445 dict_insert(nickserv_opt_dict
, "KARMA", opt_karma
);
5447 nickserv_handle_dict
= dict_new();
5448 dict_set_free_keys(nickserv_handle_dict
, free
);
5449 dict_set_free_data(nickserv_handle_dict
, free_handle_info
);
5451 nickserv_id_dict
= dict_new();
5452 dict_set_free_keys(nickserv_id_dict
, free
);
5454 nickserv_nick_dict
= dict_new();
5455 dict_set_free_data(nickserv_nick_dict
, free
);
5457 nickserv_allow_auth_dict
= dict_new();
5459 userList_init(&curr_helpers
);
5462 const char *modes
= conf_get_data("services/nickserv/modes", RECDB_QSTRING
);
5463 nickserv
= AddLocalUser(nick
, nick
, NULL
, "Nick Services", modes
);
5464 nickserv_service
= service_register(nickserv
);
5466 saxdb_register("NickServ", nickserv_saxdb_read
, nickserv_saxdb_write
);
5467 reg_exit_func(nickserv_db_cleanup
, NULL
);
5468 if(nickserv_conf
.handle_expire_frequency
)
5469 timeq_add(now
+ nickserv_conf
.handle_expire_frequency
, expire_handles
, NULL
);
5471 if(autojoin_channels
&& nickserv
) {
5472 for (i
= 0; i
< autojoin_channels
->used
; i
++) {
5473 chan
= AddChannel(autojoin_channels
->list
[i
], now
, "+nt", NULL
, NULL
);
5474 AddChannelUser(nickserv
, chan
)->modes
|= MODE_CHANOP
;
5478 ldap_do_init(nickserv_conf
);
5481 message_register_table(msgtab
);