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 2 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_FLAG_LEVELS "flag_levels"
62 #define KEY_HANDLE_EXPIRE_FREQ "handle_expire_freq"
63 #define KEY_ACCOUNT_EXPIRE_FREQ "account_expire_freq"
64 #define KEY_HANDLE_EXPIRE_DELAY "handle_expire_delay"
65 #define KEY_ACCOUNT_EXPIRE_DELAY "account_expire_delay"
66 #define KEY_NOCHAN_HANDLE_EXPIRE_DELAY "nochan_handle_expire_delay"
67 #define KEY_NOCHAN_ACCOUNT_EXPIRE_DELAY "nochan_account_expire_delay"
68 #define KEY_DICT_FILE "dict_file"
69 #define KEY_NICK "nick"
70 #define KEY_LANGUAGE "language"
71 #define KEY_AUTOGAG_ENABLED "autogag_enabled"
72 #define KEY_AUTOGAG_DURATION "autogag_duration"
73 #define KEY_AUTH_POLICER "auth_policer"
74 #define KEY_EMAIL_VISIBLE_LEVEL "email_visible_level"
75 #define KEY_EMAIL_ENABLED "email_enabled"
76 #define KEY_EMAIL_REQUIRED "email_required"
77 #define KEY_SYNC_LOG "sync_log"
78 #define KEY_COOKIE_TIMEOUT "cookie_timeout"
79 #define KEY_ACCOUNTS_PER_EMAIL "accounts_per_email"
80 #define KEY_EMAIL_SEARCH_LEVEL "email_search_level"
81 #define KEY_DEFAULT_STYLE "default_style"
84 #define KEY_PASSWD "passwd"
85 #define KEY_NICKS "nicks"
86 #define KEY_MASKS "masks"
87 #define KEY_IGNORES "ignores"
88 #define KEY_OPSERV_LEVEL "opserv_level"
89 #define KEY_FLAGS "flags"
90 #define KEY_REGISTER_ON "register"
91 #define KEY_LAST_SEEN "lastseen"
92 #define KEY_INFO "info"
93 #define KEY_USERLIST_STYLE "user_style"
94 #define KEY_SCREEN_WIDTH "screen_width"
95 #define KEY_LAST_AUTHED_HOST "last_authed_host"
96 #define KEY_LAST_QUIT_HOST "last_quit_host"
97 #define KEY_EMAIL_ADDR "email_addr"
98 #define KEY_COOKIE "cookie"
99 #define KEY_COOKIE_DATA "data"
100 #define KEY_COOKIE_TYPE "type"
101 #define KEY_COOKIE_EXPIRES "expires"
102 #define KEY_ACTIVATION "activation"
103 #define KEY_PASSWORD_CHANGE "password change"
104 #define KEY_EMAIL_CHANGE "email change"
105 #define KEY_ALLOWAUTH "allowauth"
106 #define KEY_EPITHET "epithet"
107 #define KEY_TABLE_WIDTH "table_width"
108 #define KEY_ANNOUNCEMENTS "announcements"
109 #define KEY_MAXLOGINS "maxlogins"
110 #define KEY_FAKEHOST "fakehost"
111 #define KEY_NOTE_NOTE "note"
112 #define KEY_NOTE_SETTER "setter"
113 #define KEY_NOTE_DATE "date"
115 #define KEY_LDAP_ENABLE "ldap_enable"
118 #define KEY_LDAP_HOST "ldap_host"
119 #define KEY_LDAP_PORT "ldap_port"
120 #define KEY_LDAP_BASE "ldap_base"
121 #define KEY_LDAP_DN_FMT "ldap_dn_fmt"
122 #define KEY_LDAP_VERSION "ldap_version"
123 #define KEY_LDAP_AUTOCREATE "ldap_autocreate"
124 #define KEY_LDAP_ADMIN_DN "ldap_admin_dn"
125 #define KEY_LDAP_ADMIN_PASS "ldap_admin_pass"
126 #define KEY_LDAP_FIELD_ACCOUNT "ldap_field_account"
127 #define KEY_LDAP_FIELD_PASSWORD "ldap_field_password"
128 #define KEY_LDAP_FIELD_EMAIL "ldap_field_email"
129 #define KEY_LDAP_OBJECT_CLASSES "ldap_object_classes"
130 #define KEY_LDAP_OPER_GROUP_DN "ldap_oper_group_dn"
131 #define KEY_LDAP_FIELD_GROUP_MEMBER "ldap_field_group_member"
134 #define NICKSERV_VALID_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
136 #define NICKSERV_FUNC(NAME) MODCMD_FUNC(NAME)
137 #define OPTION_FUNC(NAME) int NAME(struct svccmd *cmd, struct userNode *user, struct handle_info *hi, UNUSED_ARG(unsigned int override), unsigned int argc, char *argv[])
138 typedef OPTION_FUNC(option_func_t
);
140 DEFINE_LIST(handle_info_list
, struct handle_info
*);
142 #define NICKSERV_MIN_PARMS(N) do { \
144 reply("MSG_MISSING_PARAMS", argv[0]); \
145 svccmd_send_help_brief(user, nickserv, cmd); \
149 struct userNode
*nickserv
;
150 struct userList curr_helpers
;
151 const char *handle_flags
= HANDLE_FLAGS
;
153 extern struct string_list
*autojoin_channels
;
154 static struct module *nickserv_module
;
155 static struct service
*nickserv_service
;
156 static struct log_type
*NS_LOG
;
157 static dict_t nickserv_handle_dict
; /* contains struct handle_info* */
158 static dict_t nickserv_id_dict
; /* contains struct handle_info* */
159 static dict_t nickserv_nick_dict
; /* contains struct nick_info* */
160 static dict_t nickserv_opt_dict
; /* contains option_func_t* */
161 static dict_t nickserv_allow_auth_dict
; /* contains struct handle_info* */
162 static dict_t nickserv_email_dict
; /* contains struct handle_info_list*, indexed by email addr */
163 static char handle_inverse_flags
[256];
164 static unsigned int flag_access_levels
[32];
165 static const struct message_entry msgtab
[] = {
166 { "NSMSG_HANDLE_EXISTS", "Account $b%s$b is already registered." },
167 { "NSMSG_HANDLE_TOLONG", "The account name %s is too long. Account names must be %lu characters or less."},
168 { "NSMSG_PASSWORD_SHORT", "Your password must be at least %lu characters long." },
169 { "NSMSG_PASSWORD_ACCOUNT", "Your password may not be the same as your account name." },
170 { "NSMSG_PASSWORD_DICTIONARY", "Your password is too simple. You must choose a password that is not just a word or name." },
171 { "NSMSG_PASSWORD_READABLE", "Your password must have at least %lu digit(s), %lu capital letter(s), and %lu lower-case letter(s)." },
172 { "NSMSG_LDAP_FAIL", "There was a problem in contacting the account server (ldap): %s. Please try again later." },
173 { "NSMSG_LDAP_FAIL_EMAIL", "There was a problem in storing your email address in the account server (ldap): %s. Please try again later." },
174 { "NSMSG_PARTIAL_REGISTER", "Account has been registered to you; nick was already registered to someone else." },
175 { "NSMSG_OREGISTER_VICTIM", "%s has registered a new account for you (named %s)." },
176 { "NSMSG_OREGISTER_H_SUCCESS", "Account has been registered." },
177 { "NSMSG_REGISTER_H_SUCCESS", "Account has been registered to you." },
178 { "NSMSG_REGISTER_HN_SUCCESS", "Account and nick have been registered to you." },
179 { "NSMSG_REQUIRE_OPER", "You must be an $bIRC Operator$b to register the first account." },
180 { "NSMSG_ROOT_HANDLE", "Account %s has been granted $broot-level privileges$b." },
181 { "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." },
182 { "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." },
183 { "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." },
184 { "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." },
185 { "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." },
186 { "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." },
187 { "NSMSG_EMAIL_UNACTIVATED", "That email address already has an unused cookie outstanding. Please use the cookie or wait for it to expire." },
188 { "NSMSG_NO_COOKIE", "Your account does not have any cookie issued right now." },
189 { "NSMSG_NO_COOKIE_FOREIGN", "The account $b%s$b does not have any cookie issued right now." },
190 { "NSMSG_CANNOT_COOKIE", "You cannot use that kind of cookie when you are logged in." },
191 { "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." },
192 { "NSMSG_HANDLE_ACTIVATED", "Your account is now activated (with the password you entered when you registered). You are now authenticated to your account." },
193 { "NSMSG_PASSWORD_CHANGED", "You have successfully changed your password to what you requested with the $bresetpass$b command." },
194 { "NSMSG_EMAIL_PROHIBITED", "%s may not be used as an email address: %s" },
195 { "NSMSG_EMAIL_OVERUSED", "That email address already has an account. Use RESETPASS if you forgot your password." },
196 { "NSMSG_EMAIL_SAME", "That is the email address already there; no need to change it." },
197 { "NSMSG_EMAIL_CHANGED", "You have successfully changed your email address." },
198 { "NSMSG_BAD_COOKIE_TYPE", "Your account had bad cookie type %d; sorry. I am confused. Please report this bug." },
199 { "NSMSG_MUST_TIME_OUT", "You must wait for cookies of that type to time out." },
200 { "NSMSG_ATE_COOKIE", "I ate the cookie for your account. You may now have another." },
201 { "NSMSG_ATE_FOREIGN_COOKIE", "I ate the cookie for account $b%s$b. It may now have another." },
202 { "NSMSG_USE_RENAME", "You are already authenticated to account $b%s$b -- contact the support staff to rename your account." },
203 { "NSMSG_ALREADY_REGISTERING", "You have already used $bREGISTER$b once this session; you may not use it again." },
204 { "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 *@*)." },
205 { "NSMSG_NICK_NOT_REGISTERED", "Nick $b%s$b has not been registered to any account." },
206 { "NSMSG_HANDLE_NOT_FOUND", "Could not find your account -- did you register yet?" },
207 { "NSMSG_ALREADY_AUTHED", "You are already authed to account $b%s$b; you must reconnect to auth to a different account." },
208 { "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)" },
209 { "NSMSG_HOSTMASK_INVALID", "Your hostmask is not valid for account $b%s$b." },
210 { "NSMSG_USER_IS_SERVICE", "$b%s$b is a network service; you can only use that command on real users." },
211 { "NSMSG_USER_PREV_AUTH", "$b%s$b is already authenticated." },
212 { "NSMSG_USER_PREV_STAMP", "$b%s$b has authenticated to an account once and cannot authenticate again." },
213 { "NSMSG_BAD_MAX_LOGINS", "MaxLogins must be at most %d." },
214 { "NSMSG_BAD_ADVANCED", "Advanced must be either 1 to enable it or 0 to disable it." },
215 { "NSMSG_LANGUAGE_NOT_FOUND", "Language $b%s$b is not supported; $b%s$b was the closest available match." },
216 { "NSMSG_MAX_LOGINS", "Your account already has its limit of %d user(s) logged in." },
217 { "NSMSG_STAMPED_REGISTER", "You have already authenticated to an account once this session; you may not register a new account." },
218 { "NSMSG_STAMPED_AUTH", "You have already authenticated to an account once this session; you may not authenticate to another." },
219 { "NSMSG_STAMPED_RESETPASS", "You have already authenticated to an account once this session; you may not reset your password to authenticate again." },
220 { "NSMSG_STAMPED_AUTHCOOKIE", "You have already authenticated to an account once this session; you may not use a cookie to authenticate to another account." },
221 { "NSMSG_TITLE_INVALID", "Titles may contain only a-z, A-Z, 0-9, and '-'. Please choose another." },
222 { "NSMSG_TITLE_TRUNCATED", "That title combined with the user's account name would result in a truncated host; please choose a shorter title." },
223 { "NSMSG_FAKEHOST_INVALID", "Fake hosts must be shorter than %d characters and cannot start with a dot." },
224 { "NSMSG_HANDLEINFO_ON", "$bAccount Information for %s$b" },
225 { "NSMSG_HANDLEINFO_END", "----------End of Account Info-----------" },
226 { "NSMSG_HANDLEINFO_ID", "Account ID: %lu" },
227 { "NSMSG_HANDLEINFO_REGGED", "Registered on: %s" },
228 { "NSMSG_HANDLEINFO_LASTSEEN", "Last seen: %s" },
229 { "NSMSG_HANDLEINFO_LASTSEEN_NOW", "Last seen: Right now!" },
230 { "NSMSG_HANDLEINFO_VACATION", "On vacation." },
231 { "NSMSG_HANDLEINFO_EMAIL_ADDR", "Email address: %s" },
232 { "NSMSG_HANDLEINFO_COOKIE_ACTIVATION", "Cookie: There is currently an activation cookie issued for this account" },
233 { "NSMSG_HANDLEINFO_COOKIE_PASSWORD", "Cookie: There is currently a password change cookie issued for this account" },
234 { "NSMSG_HANDLEINFO_COOKIE_EMAIL", "Cookie: There is currently an email change cookie issued for this account" },
235 { "NSMSG_HANDLEINFO_COOKIE_ALLOWAUTH", "Cookie: There is currently an allowauth cookie issued for this account" },
236 { "NSMSG_HANDLEINFO_COOKIE_UNKNOWN", "Cookie: There is currently an unknown cookie issued for this account" },
237 { "NSMSG_HANDLEINFO_INFOLINE", "Infoline: %s" },
238 { "NSMSG_HANDLEINFO_FLAGS", "Flags: %s" },
239 { "NSMSG_HANDLEINFO_EPITHET", "Epithet: %s" },
240 { "NSMSG_HANDLEINFO_NOTE", "Note (by %s on %s): %s " },
241 { "NSMSG_HANDLEINFO_FAKEHOST", "Fake host: %s" },
242 { "NSMSG_HANDLEINFO_LAST_HOST", "Last quit hostmask: %s" },
243 { "NSMSG_HANDLEINFO_LAST_HOST_UNKNOWN", "Last quit hostmask: Unknown" },
244 { "NSMSG_HANDLEINFO_NICKS", "Nickname(s): %s" },
245 { "NSMSG_HANDLEINFO_MASKS", "Hostmask(s): %s" },
246 { "NSMSG_HANDLEINFO_IGNORES", "Ignore(s): %s" },
247 { "NSMSG_HANDLEINFO_CHANNELS", "Channel(s): %s" },
248 { "NSMSG_HANDLEINFO_CURRENT", "Current nickname(s): %s" },
249 { "NSMSG_HANDLEINFO_DNR", "Do-not-register (by %s): %s" },
250 { "NSMSG_USERINFO_AUTHED_AS", "$b%s$b is authenticated to account $b%s$b." },
251 { "NSMSG_USERINFO_NOT_AUTHED", "$b%s$b is not authenticated to any account." },
252 { "NSMSG_NICKINFO_OWNER", "Nick $b%s$b is owned by account $b%s$b." },
253 { "NSMSG_PASSWORD_INVALID", "Incorrect password; please try again." },
254 { "NSMSG_PLEASE_SET_EMAIL", "We now require email addresses for users. Please use the $bset email$b command to set your email address!" },
255 { "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)." },
256 { "NSMSG_HANDLE_SUSPENDED", "Your $b$N$b account has been suspended; you may not use it." },
257 { "NSMSG_AUTH_SUCCESS", "I recognize you." },
258 { "NSMSG_ALLOWAUTH_STAFF", "$b%s$b is a helper or oper; please use $bstaff$b after the account name to allowauth." },
259 { "NSMSG_AUTH_ALLOWED", "User $b%s$b may now authenticate to account $b%s$b." },
260 { "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." },
261 { "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." },
262 { "NSMSG_AUTH_NORMAL_ONLY", "User $b%s$b may now only authenticate to accounts with matching hostmasks." },
263 { "NSMSG_AUTH_UNSPECIAL", "User $b%s$b did not have any special auth allowance." },
264 { "NSMSG_MUST_AUTH", "You must be authenticated first." },
265 { "NSMSG_TOO_MANY_NICKS", "You have already registered the maximum permitted number of nicks." },
266 { "NSMSG_NICK_EXISTS", "Nick $b%s$b already registered." },
267 { "NSMSG_REGNICK_SUCCESS", "Nick $b%s$b has been registered to you." },
268 { "NSMSG_OREGNICK_SUCCESS", "Nick $b%s$b has been registered to account $b%s$b." },
269 { "NSMSG_PASS_SUCCESS", "Password changed." },
270 { "NSMSG_MASK_INVALID", "$b%s$b is an invalid hostmask." },
271 { "NSMSG_ADDMASK_ALREADY", "$b%s$b is already a hostmask in your account." },
272 { "NSMSG_ADDMASK_SUCCESS", "Hostmask %s added." },
273 { "NSMSG_ADDIGNORE_ALREADY", "$b%s$b is already an ignored hostmask in your account." },
274 { "NSMSG_ADDIGNORE_SUCCESS", "Hostmask %s added." },
275 { "NSMSG_DELMASK_NOTLAST", "You may not delete your last hostmask." },
276 { "NSMSG_DELMASK_SUCCESS", "Hostmask %s deleted." },
277 { "NSMSG_DELMASK_NOT_FOUND", "Unable to find mask to be deleted." },
278 { "NSMSG_OPSERV_LEVEL_BAD", "You may not promote another oper above your level." },
279 { "NSMSG_USE_CMD_PASS", "Please use the PASS command to change your password." },
280 { "NSMSG_UNKNOWN_NICK", "I know nothing about nick $b%s$b." },
281 { "NSMSG_NOT_YOUR_NICK", "The nick $b%s$b is not registered to you." },
282 { "NSMSG_NICK_USER_YOU", "I will not let you kill yourself." },
283 { "NSMSG_UNREGNICK_SUCCESS", "Nick $b%s$b has been unregistered." },
284 { "NSMSG_UNREGISTER_SUCCESS", "Account $b%s$b has been unregistered." },
285 { "NSMSG_UNREGISTER_NICKS_SUCCESS", "Account $b%s$b and all its nicks have been unregistered." },
286 { "NSMSG_HANDLE_STATS", "There are %d nicks registered to your account." },
287 { "NSMSG_HANDLE_NONE", "You are not authenticated against any account." },
288 { "NSMSG_GLOBAL_STATS", "There are %d accounts and %d nicks registered globally." },
289 { "NSMSG_GLOBAL_STATS_NONICK", "There are %d accounts registered." },
290 { "NSMSG_CANNOT_GHOST_SELF", "You may not ghost-kill yourself." },
291 { "NSMSG_CANNOT_GHOST_USER", "$b%s$b is not authed to your account; you may not ghost-kill them." },
292 { "NSMSG_GHOST_KILLED", "$b%s$b has been killed as a ghost." },
293 { "NSMSG_ON_VACATION", "You are now on vacation. Your account will be preserved until you authenticate again." },
294 { "NSMSG_NO_ACCESS", "Access denied." },
295 { "NSMSG_INVALID_FLAG", "$b%c$b is not a valid $N account flag." },
296 { "NSMSG_SET_FLAG", "Applied flags $b%s$b to %s's $N account." },
297 { "NSMSG_FLAG_PRIVILEGED", "You have insufficient access to set flag %c." },
298 { "NSMSG_DB_UNREADABLE", "Unable to read database file %s; check the log for more information." },
299 { "NSMSG_DB_MERGED", "$N merged DB from %s (in "FMT_TIME_T
".%03lu seconds)." },
300 { "NSMSG_HANDLE_CHANGED", "$b%s$b's account name has been changed to $b%s$b." },
301 { "NSMSG_BAD_HANDLE", "Account $b%s$b not registered because it is in use by a network service, is too long, or contains invalid characters." },
302 { "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." },
303 { "NSMSG_BAD_EMAIL_ADDR", "Please use a well-formed email address." },
304 { "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." },
305 { "NSMSG_ACCOUNT_SEARCH_RESULTS", "The following accounts were found:" },
306 { "NSMSG_SEARCH_MATCH", "Match: %s" },
307 { "NSMSG_INVALID_ACTION", "%s is an invalid search action." },
308 { "NSMSG_CANNOT_MERGE_SELF", "You cannot merge account $b%s$b with itself." },
309 { "NSMSG_HANDLES_MERGED", "Merged account $b%s$b into $b%s$b." },
310 { "NSMSG_RECLAIM_WARN", "%s is a registered nick - you must auth to account %s or change your nick." },
311 { "NSMSG_RECLAIM_KILL", "Unauthenticated user of nick." },
312 { "NSMSG_RECLAIMED_NONE", "You cannot manually reclaim a nick." },
313 { "NSMSG_RECLAIMED_WARN", "Sent a request for %s to change their nick." },
314 { "NSMSG_RECLAIMED_SVSNICK", "Forcibly changed %s's nick." },
315 { "NSMSG_RECLAIMED_KILL", "Disconnected %s from the network." },
316 { "NSMSG_CLONE_AUTH", "Warning: %s (%s@%s) authed to your account." },
317 { "NSMSG_SETTING_LIST", "$b$N account settings$b" },
318 { "NSMSG_SETTING_LIST_HEADER", "----------------------------------------" },
319 { "NSMSG_SETTING_LIST_END", "-------------End Of Settings------------" },
320 { "NSMSG_INVALID_OPTION", "$b%s$b is an invalid account setting." },
321 { "NSMSG_INVALID_ANNOUNCE", "$b%s$b is an invalid announcements value." },
322 { "NSMSG_SET_INFO", "$bINFO: $b%s" },
323 { "NSMSG_SET_WIDTH", "$bWIDTH: $b%d" },
324 { "NSMSG_SET_TABLEWIDTH", "$bTABLEWIDTH: $b%d" },
325 { "NSMSG_SET_COLOR", "$bCOLOR: $b%s" },
326 { "NSMSG_SET_PRIVMSG", "$bPRIVMSG: $b%s" },
327 { "NSMSG_SET_STYLE", "$bSTYLE: $b%s" },
328 { "NSMSG_SET_ANNOUNCEMENTS", "$bANNOUNCEMENTS: $b%s" },
329 { "NSMSG_SET_AUTOHIDE", "$bAUTOHIDE: $b%s" },
330 { "NSMSG_SET_PASSWORD", "$bPASSWORD: $b%s" },
331 { "NSMSG_SET_FLAGS", "$bFLAGS: $b%s" },
332 { "NSMSG_SET_EMAIL", "$bEMAIL: $b%s" },
333 { "NSMSG_SET_MAXLOGINS", "$bMAXLOGINS: $b%d" },
334 { "NSMSG_SET_ADVANCED", "$bADVANCED: $b%s" },
335 { "NSMSG_SET_LANGUAGE", "$bLANGUAGE: $b%s" },
336 { "NSMSG_SET_LEVEL", "$bLEVEL: $b%d" },
337 { "NSMSG_SET_EPITHET", "$bEPITHET: $b%s" },
338 { "NSMSG_SET_NOTE", "$bNOTE: $b%s"},
339 { "NSMSG_SET_TITLE", "$bTITLE: $b%s" },
340 { "NSMSG_SET_FAKEHOST", "$bFAKEHOST: $b%s" },
342 { "NSMSG_AUTO_OPER", "You have been auto-opered" },
343 { "NSMSG_AUTO_OPER_ADMIN", "You have been auto-admined" },
345 { "NSEMAIL_ACTIVATION_SUBJECT", "Account verification for %s" },
346 { "NSEMAIL_ACTIVATION_BODY",
347 "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"
349 "To verify your email address and complete the account registration, log on to %1$s and type the following command:\n"
350 "/msg %3$s@%4$s COOKIE %5$s %2$s\n"
351 "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"
352 "/msg %3$s@%4$s AUTH %5$s your-password\n"
353 "(Please remember to fill in 'your-password' with the actual password you gave to us when you registered.)\n"
354 "OR configure Login-On-Connect (see http://www.afternet.org/login-on-connect for instructions) to connect pre-logged in every time.\n"
356 "If you did NOT request this account, you do not need to do anything.\n"
357 "Please contact the %1$s staff if you have questions, and be sure to check our website." },
358 { "NSEMAIL_ACTIVATION_BODY_WEB",
359 "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"
361 "To verify your email address and complete the account registration, visit the following URL:\n"
362 "http://www.afternet.org/index.php?option=com_registration&task=activate&username=%5$s&cookie=%2$s\n"
364 "If you did NOT request this account, you do not need to do anything.\n"
365 "Please contact the %1$s staff if you have questions, and be sure to check our website." },
366 { "NSEMAIL_PASSWORD_CHANGE_SUBJECT", "Password change verification on %s" },
367 { "NSEMAIL_PASSWORD_CHANGE_BODY",
368 "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"
369 "To complete the password change, log on to %1$s and type the following command:\n"
370 "/msg %3$s@%4$s COOKIE %5$s %2$s\n"
371 "If you did NOT request your password to be changed, you do not need to do anything.\n"
372 "Please contact the %1$s staff if you have questions." },
373 { "NSEMAIL_PASSWORD_CHANGE_BODY_WEB",
374 "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"
375 "To complete the password change, click the following URL:\n"
376 "http://www.afternet.org/index.php?option=com_registration&task=passcookie&username=%5$s&cookie=%2$s\n"
377 "If you did NOT request your password to be changed, you do not need to do anything.\n"
378 "Please contact the %1$s staff if you have questions." },
379 { "NSEMAIL_EMAIL_CHANGE_SUBJECT", "Email address change verification for %s" },
380 #ifdef stupid_verify_old_email
381 { "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." },
382 { "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." },
384 { "NSEMAIL_EMAIL_VERIFY_SUBJECT", "Email address verification for %s" },
385 { "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." },
386 { "NSEMAIL_ALLOWAUTH_SUBJECT", "Authentication allowed for %s" },
387 { "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." },
388 { "NSMSG_NOT_VALID_FAKEHOST_DOT", "$b%s$b is not a valid vhost. (needs at least one dot)" },
389 { "NSMSG_NOT_VALID_FAKEHOST_AT", "$b%s$b is not a valid vhost. (it can not have a '@')" },
390 { "NSMSG_DENIED_FAKEHOST_WORD", "Access denied because there's a prohibited word in $b%s$b (%s)." },
391 { "NSMSG_NOT_VALID_FAKEHOST_LEN", "$b%s$b is not a valid vhost. (can only be 63 characters)" },
392 { "NSMSG_NOT_VALID_FAKEHOST_TLD_LEN", "$b%s$b is not a valid vhost. (TLD can only be 4 characters and less)" },
393 { "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." },
394 { "CHECKPASS_YES", "Yes." },
395 { "CHECKPASS_NO", "No." },
396 { "NSMSG_DEFCON_NO_NEW_NICKS", "You cannot register new %s at this time, please try again soon" },
400 static void nickserv_reclaim(struct userNode
*user
, struct nick_info
*ni
, enum reclaim_action action
);
401 static void nickserv_reclaim_p(void *data
);
403 struct nickserv_config nickserv_conf
;
405 /* We have 2^32 unique account IDs to use. */
406 unsigned long int highest_id
= 0;
409 canonicalize_hostmask(char *mask
)
411 char *out
= mask
, *temp
;
412 if ((temp
= strchr(mask
, '!'))) {
414 while (*temp
) *out
++ = *temp
++;
420 static struct handle_note
*
421 nickserv_add_note(const char *setter
, time_t date
, const char *text
)
423 struct handle_note
*note
= calloc(1, sizeof(*note
) + strlen(text
));
425 strncpy(note
->setter
, setter
, sizeof(note
->setter
)-1);
427 memcpy(note
->note
, text
, strlen(text
));
431 static struct handle_info
*
432 register_handle(const char *handle
, const char *passwd
, UNUSED_ARG(unsigned long id
))
434 struct handle_info
*hi
;
436 hi
= calloc(1, sizeof(*hi
));
437 hi
->userlist_style
= HI_DEFAULT_STYLE
;
438 hi
->announcements
= '?';
439 hi
->handle
= strdup(handle
);
440 safestrncpy(hi
->passwd
, passwd
, sizeof(hi
->passwd
));
442 dict_insert(nickserv_handle_dict
, hi
->handle
, hi
);
448 register_nick(const char *nick
, struct handle_info
*owner
)
450 struct nick_info
*ni
;
451 ni
= malloc(sizeof(struct nick_info
));
452 safestrncpy(ni
->nick
, nick
, sizeof(ni
->nick
));
454 ni
->next
= owner
->nicks
;
456 dict_insert(nickserv_nick_dict
, ni
->nick
, ni
);
460 delete_nick(struct nick_info
*ni
)
462 struct nick_info
*last
, *next
;
463 struct userNode
*user
;
464 /* Check to see if we should mark a user as unregistered. */
465 if ((user
= GetUserH(ni
->nick
)) && IsReggedNick(user
)) {
466 user
->modes
&= ~FLAGS_REGNICK
;
469 /* Remove ni from the nick_info linked list. */
470 if (ni
== ni
->owner
->nicks
) {
471 ni
->owner
->nicks
= ni
->next
;
473 last
= ni
->owner
->nicks
;
479 last
->next
= next
->next
;
481 dict_remove(nickserv_nick_dict
, ni
->nick
);
484 static unreg_func_t
*unreg_func_list
;
485 static unsigned int unreg_func_size
= 0, unreg_func_used
= 0;
488 reg_unreg_func(unreg_func_t func
)
490 if (unreg_func_used
== unreg_func_size
) {
491 if (unreg_func_size
) {
492 unreg_func_size
<<= 1;
493 unreg_func_list
= realloc(unreg_func_list
, unreg_func_size
*sizeof(unreg_func_t
));
496 unreg_func_list
= malloc(unreg_func_size
*sizeof(unreg_func_t
));
499 unreg_func_list
[unreg_func_used
++] = func
;
503 nickserv_free_cookie(void *data
)
505 struct handle_cookie
*cookie
= data
;
506 if (cookie
->hi
) cookie
->hi
->cookie
= NULL
;
507 if (cookie
->data
) free(cookie
->data
);
512 free_handle_info(void *vhi
)
514 struct handle_info
*hi
= vhi
;
516 free_string_list(hi
->masks
);
517 free_string_list(hi
->ignores
);
521 delete_nick(hi
->nicks
);
527 timeq_del(hi
->cookie
->expires
, nickserv_free_cookie
, hi
->cookie
, 0);
528 nickserv_free_cookie(hi
->cookie
);
530 if (hi
->email_addr
) {
531 struct handle_info_list
*hil
= dict_find(nickserv_email_dict
, hi
->email_addr
, NULL
);
532 handle_info_list_remove(hil
, hi
);
534 dict_remove(nickserv_email_dict
, hi
->email_addr
);
539 static void set_user_handle_info(struct userNode
*user
, struct handle_info
*hi
, int stamp
);
542 nickserv_unregister_handle(struct handle_info
*hi
, struct userNode
*notify
, struct userNode
*bot
)
545 struct userNode
*uNode
;
549 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
550 if( (rc
= ldap_delete_account(hi
->handle
)) != LDAP_SUCCESS
) {
552 send_message(notify
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
554 if(rc
!= LDAP_NO_SUCH_OBJECT
)
555 return false; /* if theres noone there to delete, its kinda ok, right ?:) */
559 for (n
=0; n
<unreg_func_used
; n
++)
560 unreg_func_list
[n
](notify
, hi
);
562 if (nickserv_conf
.sync_log
) {
563 uNode
= GetUserH(hi
->users
->nick
);
567 set_user_handle_info(hi
->users
, NULL
, 0);
570 if (nickserv_conf
.disable_nicks
)
571 send_message(notify
, bot
, "NSMSG_UNREGISTER_SUCCESS", hi
->handle
);
573 send_message(notify
, bot
, "NSMSG_UNREGISTER_NICKS_SUCCESS", hi
->handle
);
576 if (nickserv_conf
.sync_log
)
577 SyncLog("UNREGISTER %s", hi
->handle
);
579 dict_remove(nickserv_handle_dict
, hi
->handle
);
584 get_handle_info(const char *handle
)
586 return dict_find(nickserv_handle_dict
, handle
, 0);
590 get_nick_info(const char *nick
)
592 return nickserv_conf
.disable_nicks
? 0 : dict_find(nickserv_nick_dict
, nick
, 0);
596 find_handle_in_channel(struct chanNode
*channel
, struct handle_info
*handle
, struct userNode
*except
)
601 for (nn
=0; nn
<channel
->members
.used
; ++nn
) {
602 mn
= channel
->members
.list
[nn
];
603 if ((mn
->user
!= except
) && (mn
->user
->handle_info
== handle
))
610 oper_has_access(struct userNode
*user
, struct userNode
*bot
, unsigned int min_level
, unsigned int quiet
) {
611 if (!user
->handle_info
) {
613 send_message(user
, bot
, "MSG_AUTHENTICATE");
617 if (!IsOper(user
) && (!IsHelping(user
) || min_level
)) {
619 send_message(user
, bot
, "NSMSG_NO_ACCESS");
623 if (HANDLE_FLAGGED(user
->handle_info
, OPER_SUSPENDED
)) {
625 send_message(user
, bot
, "MSG_OPER_SUSPENDED");
629 if (user
->handle_info
->opserv_level
< min_level
) {
631 send_message(user
, bot
, "NSMSG_NO_ACCESS");
639 is_valid_handle(const char *handle
)
641 struct userNode
*user
;
642 /* cant register a juped nick/service nick as handle, to prevent confusion */
643 user
= GetUserH(handle
);
644 if (user
&& IsLocal(user
))
646 /* check against maximum length */
647 if (strlen(handle
) > NICKSERV_HANDLE_LEN
)
649 /* for consistency, only allow account names that could be nicks */
650 if (!is_valid_nick(handle
))
652 /* disallow account names that look like bad words */
653 if (opserv_bad_channel(handle
))
655 /* test either regex or containing all valid chars */
656 if (nickserv_conf
.valid_handle_regex_set
) {
657 int err
= regexec(&nickserv_conf
.valid_handle_regex
, handle
, 0, 0, 0);
660 buff
[regerror(err
, &nickserv_conf
.valid_handle_regex
, buff
, sizeof(buff
))] = 0;
661 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
665 return !handle
[strspn(handle
, NICKSERV_VALID_CHARS
)];
670 is_registerable_nick(const char *nick
)
672 /* make sure it could be used as an account name */
673 if (!is_valid_handle(nick
))
676 if (strlen(nick
) > NICKLEN
)
678 /* test either regex or as valid handle */
679 if (nickserv_conf
.valid_nick_regex_set
) {
680 int err
= regexec(&nickserv_conf
.valid_nick_regex
, nick
, 0, 0, 0);
683 buff
[regerror(err
, &nickserv_conf
.valid_nick_regex
, buff
, sizeof(buff
))] = 0;
684 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
690 /* this has been replaced with one in tools.c
693 is_valid_email_addr(const char *email)
695 return strchr(email, '@') != NULL;
701 visible_email_addr(struct userNode
*user
, struct handle_info
*hi
)
703 if (hi
->email_addr
) {
704 if (oper_has_access(user
, nickserv
, nickserv_conf
.email_visible_level
, 1)) {
705 return hi
->email_addr
;
715 smart_get_handle_info(struct userNode
*service
, struct userNode
*user
, const char *name
)
717 struct handle_info
*hi
;
718 struct userNode
*target
;
722 if (!(hi
= get_handle_info(++name
))) {
723 send_message(user
, service
, "MSG_HANDLE_UNKNOWN", name
);
728 if (!(target
= GetUserH(name
))) {
729 send_message(user
, service
, "MSG_NICK_UNKNOWN", name
);
732 if (IsLocal(target
)) {
733 if (IsService(target
))
734 send_message(user
, service
, "NSMSG_USER_IS_SERVICE", target
->nick
);
736 send_message(user
, service
, "MSG_USER_AUTHENTICATE", target
->nick
);
739 if (!(hi
= target
->handle_info
)) {
740 send_message(user
, service
, "MSG_USER_AUTHENTICATE", target
->nick
);
748 oper_outranks(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
) {
749 if (user
->handle_info
->opserv_level
> hi
->opserv_level
)
751 if (user
->handle_info
->opserv_level
== hi
->opserv_level
) {
752 if ((user
->handle_info
->opserv_level
== 1000)
753 || (user
->handle_info
== hi
)
754 || ((user
->handle_info
->opserv_level
== 0)
755 && !(HANDLE_FLAGGED(hi
, SUPPORT_HELPER
) || HANDLE_FLAGGED(hi
, NETWORK_HELPER
))
756 && HANDLE_FLAGGED(user
->handle_info
, HELPING
))) {
760 reply("MSG_USER_OUTRANKED", hi
->handle
);
765 get_victim_oper(struct svccmd
*cmd
, struct userNode
*user
, const char *target
)
767 struct handle_info
*hi
;
768 if (!(hi
= smart_get_handle_info(nickserv
, user
, target
)))
770 if (HANDLE_FLAGGED(user
->handle_info
, OPER_SUSPENDED
)) {
771 send_message(user
, nickserv
, "MSG_OPER_SUSPENDED");
774 return oper_outranks(cmd
, user
, hi
) ? hi
: NULL
;
778 valid_user_for(struct userNode
*user
, struct handle_info
*hi
)
782 /* If no hostmasks on the account, allow it. */
783 if (!hi
->masks
->used
)
785 /* If any hostmask matches, allow it. */
786 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
787 if (user_matches_glob(user
, hi
->masks
->list
[ii
], 0))
789 /* If they are allowauthed to this account, allow it (removing the aa). */
790 if (dict_find(nickserv_allow_auth_dict
, user
->nick
, NULL
) == hi
) {
791 dict_remove(nickserv_allow_auth_dict
, user
->nick
);
794 /* The user is not allowed to use this account. */
799 is_secure_password(const char *handle
, const char *pass
, struct userNode
*user
)
802 unsigned int cnt_digits
= 0, cnt_upper
= 0, cnt_lower
= 0;
806 if (len
< nickserv_conf
.password_min_length
) {
808 send_message(user
, nickserv
, "NSMSG_PASSWORD_SHORT", nickserv_conf
.password_min_length
);
811 if (!irccasecmp(pass
, handle
)) {
813 send_message(user
, nickserv
, "NSMSG_PASSWORD_ACCOUNT");
816 dict_find(nickserv_conf
.weak_password_dict
, pass
, &p
);
819 send_message(user
, nickserv
, "NSMSG_PASSWORD_DICTIONARY");
822 for (i
=0; i
<len
; i
++) {
823 if (isdigit(pass
[i
]))
825 if (isupper(pass
[i
]))
827 if (islower(pass
[i
]))
830 if ((cnt_lower
< nickserv_conf
.password_min_lower
)
831 || (cnt_upper
< nickserv_conf
.password_min_upper
)
832 || (cnt_digits
< nickserv_conf
.password_min_digits
)) {
834 send_message(user
, nickserv
, "NSMSG_PASSWORD_READABLE", nickserv_conf
.password_min_digits
, nickserv_conf
.password_min_upper
, nickserv_conf
.password_min_lower
);
840 static auth_func_t
*auth_func_list
;
841 static unsigned int auth_func_size
= 0, auth_func_used
= 0;
844 reg_auth_func(auth_func_t func
)
846 if (auth_func_used
== auth_func_size
) {
847 if (auth_func_size
) {
848 auth_func_size
<<= 1;
849 auth_func_list
= realloc(auth_func_list
, auth_func_size
*sizeof(auth_func_t
));
852 auth_func_list
= malloc(auth_func_size
*sizeof(auth_func_t
));
855 auth_func_list
[auth_func_used
++] = func
;
858 static handle_rename_func_t
*rf_list
;
859 static unsigned int rf_list_size
, rf_list_used
;
862 reg_handle_rename_func(handle_rename_func_t func
)
864 if (rf_list_used
== rf_list_size
) {
867 rf_list
= realloc(rf_list
, rf_list_size
*sizeof(rf_list
[0]));
870 rf_list
= malloc(rf_list_size
*sizeof(rf_list
[0]));
873 rf_list
[rf_list_used
++] = func
;
877 generate_fakehost(struct handle_info
*handle
)
879 struct userNode
*target
;
880 extern const char *hidden_host_suffix
;
881 static char buffer
[HOSTLEN
+1];
885 if (!handle
->fakehost
) {
886 data
= conf_get_data("server/hidden_host_type", RECDB_QSTRING
);
891 snprintf(buffer
, sizeof(buffer
), "%s.%s", handle
->handle
, hidden_host_suffix
);
892 else if (style
== 2) {
893 /* Due to the way fakehost is coded theres no way i can
894 get the exact user, so for now ill just take the first
896 for (target
= handle
->users
; target
; target
= target
->next_authed
)
899 snprintf(buffer
, sizeof(buffer
), "%s", target
->crypthost
);
902 } else if (handle
->fakehost
[0] == '.') {
903 /* A leading dot indicates the stored value is actually a title. */
904 snprintf(buffer
, sizeof(buffer
), "%s.%s.%s", handle
->handle
, handle
->fakehost
+1, nickserv_conf
.titlehost_suffix
);
907 return handle
->fakehost
;
911 apply_fakehost(struct handle_info
*handle
)
913 struct userNode
*target
;
918 fake
= generate_fakehost(handle
);
919 for (target
= handle
->users
; target
; target
= target
->next_authed
)
920 assign_fakehost(target
, fake
, 1);
923 void send_func_list(struct userNode
*user
)
926 struct handle_info
*old_info
;
928 old_info
= user
->handle_info
;
930 for (n
=0; n
<auth_func_used
; n
++)
931 auth_func_list
[n
](user
, old_info
);
935 set_user_handle_info(struct userNode
*user
, struct handle_info
*hi
, int stamp
)
938 struct handle_info
*old_info
;
940 /* This can happen if somebody uses COOKIE while authed, or if
941 * they re-auth to their current handle (which is silly, but users
943 if (user
->handle_info
== hi
)
946 if (user
->handle_info
) {
947 struct userNode
*other
;
950 userList_remove(&curr_helpers
, user
);
952 /* remove from next_authed linked list */
953 if (user
->handle_info
->users
== user
) {
954 user
->handle_info
->users
= user
->next_authed
;
956 for (other
= user
->handle_info
->users
;
957 other
->next_authed
!= user
;
958 other
= other
->next_authed
) ;
959 other
->next_authed
= user
->next_authed
;
961 /* if nobody left on old handle, and they're not an oper, remove !god */
962 if (!user
->handle_info
->users
&& !user
->handle_info
->opserv_level
)
963 HANDLE_CLEAR_FLAG(user
->handle_info
, HELPING
);
964 /* record them as being last seen at this time */
965 user
->handle_info
->lastseen
= now
;
966 /* and record their hostmask */
967 snprintf(user
->handle_info
->last_quit_host
, sizeof(user
->handle_info
->last_quit_host
), "%s@%s", user
->ident
, user
->hostname
);
969 old_info
= user
->handle_info
;
970 user
->handle_info
= hi
;
971 if (hi
&& !hi
->users
&& !hi
->opserv_level
)
972 HANDLE_CLEAR_FLAG(hi
, HELPING
);
974 /* Call auth handlers */
975 if (!GetUserH(user
->nick
))
979 struct nick_info
*ni
;
981 HANDLE_CLEAR_FLAG(hi
, FROZEN
);
982 if (nickserv_conf
.warn_clone_auth
) {
983 struct userNode
*other
;
984 for (other
= hi
->users
; other
; other
= other
->next_authed
)
985 send_message(other
, nickserv
, "NSMSG_CLONE_AUTH", user
->nick
, user
->ident
, user
->hostname
);
988 /* Add this auth to users list of current auths */
989 user
->next_authed
= hi
->users
;
992 /* Add to helpers list */
994 userList_append(&curr_helpers
, user
);
996 /* Set the fakehost */
997 if (hi
->fakehost
|| old_info
)
1001 #ifdef WITH_PROTOCOL_P10
1002 /* Stamp users with their account name. */
1003 char *id
= hi
->handle
;
1005 const char *id
= "???";
1007 /* Mark all the nicks registered to this
1008 * account as registered nicks
1009 * - Why not just this one? -rubin */
1010 if (!nickserv_conf
.disable_nicks
) {
1011 struct nick_info
*ni
;
1012 for (ni
= hi
->nicks
; ni
; ni
= ni
->next
) {
1013 if (!irccasecmp(user
->nick
, ni
->nick
)) {
1014 user
->modes
|= FLAGS_REGNICK
;
1019 /* send the account to the ircd */
1020 StampUser(user
, id
, hi
->registered
);
1023 /* Stop trying to kick this user off their nick */
1024 if ((ni
= get_nick_info(user
->nick
)) && (ni
->owner
== hi
))
1025 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
1027 /* We cannot clear the user's account ID, unfortunately. */
1028 user
->next_authed
= NULL
;
1031 /* Call auth handlers */
1032 if (GetUserH(user
->nick
)) {
1033 for (n
=0; n
<auth_func_used
; n
++)
1034 auth_func_list
[n
](user
, old_info
);
1038 static struct handle_info
*
1039 nickserv_register(struct userNode
*user
, struct userNode
*settee
, const char *handle
, const char *passwd
, int no_auth
)
1041 struct handle_info
*hi
;
1042 struct nick_info
*ni
;
1043 char crypted
[MD5_CRYPT_LENGTH
];
1045 if ((hi
= dict_find(nickserv_handle_dict
, handle
, NULL
))) {
1046 send_message(user
, nickserv
, "NSMSG_HANDLE_EXISTS", handle
);
1050 if(strlen(handle
) > 15)
1052 send_message(user
, nickserv
, "NSMSG_HANDLE_TOLONG", handle
, 15);
1056 if (!is_secure_password(handle
, passwd
, user
))
1061 rc
= ldap_do_add(handle
, passwd
, NULL
);
1062 if(LDAP_SUCCESS
!= rc
&& LDAP_ALREADY_EXISTS
!= rc
) {
1063 send_message(user
, nickserv
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
1067 cryptpass(passwd
, crypted
);
1068 hi
= register_handle(handle
, crypted
, 0);
1069 hi
->masks
= alloc_string_list(1);
1070 hi
->ignores
= alloc_string_list(1);
1072 hi
->language
= lang_C
;
1073 hi
->registered
= now
;
1075 hi
->flags
= HI_DEFAULT_FLAGS
;
1076 if (settee
&& !no_auth
)
1077 set_user_handle_info(settee
, hi
, 1);
1080 send_message(user
, nickserv
, "NSMSG_OREGISTER_H_SUCCESS");
1081 else if (nickserv_conf
.disable_nicks
)
1082 send_message(user
, nickserv
, "NSMSG_REGISTER_H_SUCCESS");
1083 else if ((ni
= dict_find(nickserv_nick_dict
, user
->nick
, NULL
)))
1084 send_message(user
, nickserv
, "NSMSG_PARTIAL_REGISTER");
1086 register_nick(user
->nick
, hi
);
1087 send_message(user
, nickserv
, "NSMSG_REGISTER_HN_SUCCESS");
1089 if (settee
&& (user
!= settee
))
1090 send_message(settee
, nickserv
, "NSMSG_OREGISTER_VICTIM", user
->nick
, hi
->handle
);
1095 nickserv_bake_cookie(struct handle_cookie
*cookie
)
1097 cookie
->hi
->cookie
= cookie
;
1098 timeq_add(cookie
->expires
, nickserv_free_cookie
, cookie
);
1101 /* Contributed by the great sneep of afternet ;) */
1102 /* Since this gets used in a URL, we want to avoid stuff that confuses
1103 * email clients such as ] and ?. a-z, 0-9 only.
1105 void genpass(char *str
, int len
)
1110 for(i
= 0; i
< len
; i
++)
1114 c
= (char)((float)rand() / (float)RAND_MAX
* (float)256);
1115 } while(!((c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z') || (c
>= '0' && c
<= '9')));
1123 nickserv_make_cookie(struct userNode
*user
, struct handle_info
*hi
, enum cookie_type type
, const char *cookie_data
, int weblink
)
1125 struct handle_cookie
*cookie
;
1126 char subject
[128], body
[4096], *misc
;
1127 const char *netname
, *fmt
;
1131 send_message(user
, nickserv
, "NSMSG_COOKIE_LIVE", hi
->handle
);
1135 cookie
= calloc(1, sizeof(*cookie
));
1137 cookie
->type
= type
;
1138 cookie
->data
= cookie_data
? strdup(cookie_data
) : NULL
;
1140 cookie
->expires
= now
+ nickserv_conf
.cookie_timeout
;
1141 /* Adding dedicated password gen function for more control -Rubin */
1142 genpass(cookie
->cookie
, 10);
1144 *inttobase64(cookie->cookie, rand(), 5);
1145 *inttobase64(cookie->cookie+5, rand(), 5);
1148 netname
= nickserv_conf
.network_name
;
1151 switch (cookie
->type
) {
1153 hi
->passwd
[0] = 0; /* invalidate password */
1154 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_REGISTER");
1155 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_SUBJECT");
1156 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1159 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_BODY_WEB");
1161 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_BODY");
1163 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1166 case PASSWORD_CHANGE
:
1167 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_RESETPASS");
1168 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_SUBJECT");
1169 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1171 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_BODY_WEB");
1173 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_BODY");
1174 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1177 misc
= hi
->email_addr
;
1178 hi
->email_addr
= cookie
->data
;
1179 #ifdef stupid_verify_old_email
1181 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_EMAIL_2");
1182 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_SUBJECT");
1183 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1184 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_BODY_NEW");
1185 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
+COOKIELEN
/2, nickserv
->nick
, self
->name
, hi
->handle
, COOKIELEN
/2);
1186 sendmail(nickserv
, hi
, subject
, body
, 1);
1187 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_BODY_OLD");
1188 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
, COOKIELEN
/2, hi
->email_addr
);
1191 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_EMAIL_1");
1192 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_VERIFY_SUBJECT");
1193 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1194 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_VERIFY_BODY");
1195 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1196 sendmail(nickserv
, hi
, subject
, body
, 1);
1198 #ifdef stupid_verify_old_email
1201 hi
->email_addr
= misc
;
1204 fmt
= handle_find_message(hi
, "NSEMAIL_ALLOWAUTH_SUBJECT");
1205 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1206 fmt
= handle_find_message(hi
, "NSEMAIL_ALLOWAUTH_BODY");
1207 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1208 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_AUTH");
1211 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d in nickserv_make_cookie.", cookie
->type
);
1215 sendmail(nickserv
, hi
, subject
, body
, first_time
);
1216 nickserv_bake_cookie(cookie
);
1220 nickserv_eat_cookie(struct handle_cookie
*cookie
)
1222 cookie
->hi
->cookie
= NULL
;
1223 timeq_del(cookie
->expires
, nickserv_free_cookie
, cookie
, 0);
1224 nickserv_free_cookie(cookie
);
1228 nickserv_free_email_addr(void *data
)
1230 handle_info_list_clean(data
);
1235 nickserv_set_email_addr(struct handle_info
*hi
, const char *new_email_addr
)
1237 struct handle_info_list
*hil
;
1238 /* Remove from old handle_info_list ... */
1239 if (hi
->email_addr
&& (hil
= dict_find(nickserv_email_dict
, hi
->email_addr
, 0))) {
1240 handle_info_list_remove(hil
, hi
);
1241 if (!hil
->used
) dict_remove(nickserv_email_dict
, hil
->tag
);
1242 hi
->email_addr
= NULL
;
1244 /* Add to the new list.. */
1245 if (new_email_addr
) {
1246 if (!(hil
= dict_find(nickserv_email_dict
, new_email_addr
, 0))) {
1247 hil
= calloc(1, sizeof(*hil
));
1248 hil
->tag
= strdup(new_email_addr
);
1249 handle_info_list_init(hil
);
1250 dict_insert(nickserv_email_dict
, hil
->tag
, hil
);
1252 handle_info_list_append(hil
, hi
);
1253 hi
->email_addr
= hil
->tag
;
1257 static NICKSERV_FUNC(cmd_register
)
1260 struct handle_info
*hi
;
1261 const char *email_addr
, *password
;
1262 char syncpass
[MD5_CRYPT_LENGTH
];
1263 int no_auth
, weblink
;
1265 if (checkDefCon(DEFCON_NO_NEW_NICKS
) && !IsOper(user
)) {
1266 reply("NSMSG_DEFCON_NO_NEW_NICKS", nickserv_conf
.disable_nicks
? "accounts" : "nicknames");
1270 if (!IsOper(user
) && !dict_size(nickserv_handle_dict
)) {
1271 /* Require the first handle registered to belong to someone +o. */
1272 reply("NSMSG_REQUIRE_OPER");
1276 if (user
->handle_info
) {
1277 reply("NSMSG_USE_RENAME", user
->handle_info
->handle
);
1281 if (IsRegistering(user
)) {
1282 reply("NSMSG_ALREADY_REGISTERING");
1286 if (IsStamped(user
)) {
1287 /* Unauthenticated users might still have been stamped
1288 previously and could therefore have a hidden host;
1289 do not allow them to register a new account. */
1290 reply("NSMSG_STAMPED_REGISTER");
1294 NICKSERV_MIN_PARMS((unsigned)3 + nickserv_conf
.email_required
);
1296 irc_strtolower(argv
[1]);
1297 if (!is_valid_handle(argv
[1])) {
1298 reply("NSMSG_BAD_HANDLE", argv
[1]);
1303 if ((argc
>= 4) && nickserv_conf
.email_enabled
) {
1304 struct handle_info_list
*hil
;
1307 /* Remember email address. */
1308 email_addr
= argv
[3];
1310 /* Check that the email address looks valid.. */
1311 if (!valid_email(email_addr
)) {
1312 reply("NSMSG_BAD_EMAIL_ADDR");
1316 /* .. and that we are allowed to send to it. */
1317 if ((str
= sendmail_prohibited_address(email_addr
))) {
1318 reply("NSMSG_EMAIL_PROHIBITED", email_addr
, str
);
1322 /* If we do email verify, make sure we don't spam the address. */
1323 if ((hil
= dict_find(nickserv_email_dict
, email_addr
, NULL
))) {
1325 for (nn
=0; nn
<hil
->used
; nn
++) {
1326 if (hil
->list
[nn
]->cookie
) {
1327 reply("NSMSG_EMAIL_UNACTIVATED");
1331 if (hil
->used
>= nickserv_conf
.handles_per_email
) {
1332 reply("NSMSG_EMAIL_OVERUSED");
1345 /* Webregister hack - send URL instead of IRC cookie
1348 if((argc
>= 5) && !strcmp(argv
[4],"WEBLINK"))
1352 if (!(hi
= nickserv_register(user
, user
, argv
[1], password
, no_auth
)))
1354 /* Add any masks they should get. */
1355 if (nickserv_conf
.default_hostmask
) {
1356 string_list_append(hi
->masks
, strdup("*@*"));
1358 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
1359 if (irc_in_addr_is_valid(user
->ip
) && !irc_pton(&ip
, NULL
, user
->hostname
))
1360 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_BYIP
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
1363 /* If they're the first to register, give them level 1000. */
1364 if (dict_size(nickserv_handle_dict
) == 1) {
1365 hi
->opserv_level
= 1000;
1366 reply("NSMSG_ROOT_HANDLE", argv
[1]);
1369 /* Set their email address. */
1372 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1374 if((rc
= ldap_do_modify(hi
->handle
, NULL
, email_addr
)) != LDAP_SUCCESS
) {
1375 /* Falied to update email in ldap, but still
1376 * updated it here.. what should we do? */
1377 reply("NSMSG_LDAP_FAIL_EMAIL", ldap_err2string(rc
));
1379 nickserv_set_email_addr(hi
, email_addr
);
1383 nickserv_set_email_addr(hi
, email_addr
);
1386 nickserv_set_email_addr(hi
, email_addr
);
1390 /* If they need to do email verification, tell them. */
1392 nickserv_make_cookie(user
, hi
, ACTIVATION
, hi
->passwd
, weblink
);
1394 /* Set registering flag.. */
1395 user
->modes
|= FLAGS_REGISTERING
;
1397 if (nickserv_conf
.sync_log
) {
1398 cryptpass(password
, syncpass
);
1400 * An 0 is only sent if theres no email address. Thios should only happen if email functions are
1401 * disabled which they wont be for us. Email Required MUST be set on if you are using this.
1404 SyncLog("REGISTER %s %s %s %s", hi
->handle
, syncpass
, email_addr
? email_addr
: "0", user
->info
);
1407 /* this wont work if email is required .. */
1408 process_adduser_pending(user
);
1413 static NICKSERV_FUNC(cmd_oregister
)
1415 struct userNode
*settee
= NULL
;
1416 struct handle_info
*hi
;
1417 char* account
= NULL
;
1423 NICKSERV_MIN_PARMS(3);
1427 irc_strtolower(account
);
1428 if (nickserv_conf
.email_required
) {
1429 NICKSERV_MIN_PARMS(4);
1431 if (argc
>= 5) {/* take: "acct pass email mask nick" or "acct pass email mask" or "acct pass email nick" */
1432 if (strchr(argv
[4], '@') || argc
>= 6) /* If @, its mask not nick */
1442 if (argc
>= 4) {/* take: "account pass mask nick" or "account pass mask" or "account pass nick" */
1443 if (strchr(argv
[3], '@') || argc
>= 5) /* If @, its mask not nick */
1452 /* If they passed a nick, look for that user.. */
1453 if (nick
&& !(settee
= GetUserH(nick
))) {
1454 reply("MSG_NICK_UNKNOWN", argv
[4]);
1457 /* If the setee is already authed, we cant add a 2nd account for them.. */
1458 if (settee
&& settee
->handle_info
) {
1459 reply("NSMSG_USER_PREV_AUTH", settee
->nick
);
1462 /* If there is no default mask in the conf, and they didn't pass a mask,
1463 * but we did find a user by nick, generate the mask */
1465 if (nickserv_conf
.default_hostmask
)
1468 mask
= generate_hostmask(settee
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
1470 reply("NSMSG_REGISTER_BAD_NICKMASK");
1475 if (!(hi
= nickserv_register(user
, settee
, account
, pass
, 0))) {
1476 return 0; /* error reply handled by above */
1480 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1482 if((rc
= ldap_do_modify(hi
->handle
, NULL
, email
)) != LDAP_SUCCESS
) {
1483 /* Falied to update email in ldap, but still
1484 * updated it here.. what should we do? */
1485 reply("NSMSG_LDAP_FAIL_EMAIL", ldap_err2string(rc
));
1487 nickserv_set_email_addr(hi
, email
);
1491 nickserv_set_email_addr(hi
, email
);
1494 nickserv_set_email_addr(hi
, email
);
1498 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
1499 string_list_append(hi
->masks
, mask_canonicalized
);
1502 if (nickserv_conf
.sync_log
)
1503 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, email
? email
: "@", user
->info
); /* Send just @ for email if none */
1508 nickserv_ignore(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, char *mask
)
1511 struct userNode
*target
;
1512 char *new_mask
= strdup(pretty_mask(mask
));
1513 for (i
=0; i
<hi
->ignores
->used
; i
++) {
1514 if (!irccasecmp(new_mask
, hi
->ignores
->list
[i
])) {
1515 reply("NSMSG_ADDIGNORE_ALREADY", new_mask
);
1520 string_list_append(hi
->ignores
, new_mask
);
1521 reply("NSMSG_ADDIGNORE_SUCCESS", new_mask
);
1523 for (target
= hi
->users
; target
; target
= target
->next_authed
) {
1524 irc_silence(target
, new_mask
, 1);
1529 static NICKSERV_FUNC(cmd_addignore
)
1531 NICKSERV_MIN_PARMS(2);
1533 return nickserv_ignore(cmd
, user
, user
->handle_info
, argv
[1]);
1536 static NICKSERV_FUNC(cmd_oaddignore
)
1538 struct handle_info
*hi
;
1540 NICKSERV_MIN_PARMS(3);
1541 if (!(hi
= get_victim_oper(cmd
, user
, argv
[1])))
1544 return nickserv_ignore(cmd
, user
, hi
, argv
[2]);
1548 nickserv_delignore(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, char *del_mask
)
1551 struct userNode
*target
;
1552 char *pmask
= strdup(pretty_mask(del_mask
));
1553 for (i
=0; i
<hi
->ignores
->used
; i
++) {
1554 if (!strcmp(pmask
, hi
->ignores
->list
[i
]) || !strcmp(del_mask
, hi
->ignores
->list
[i
])) {
1555 char *old_mask
= hi
->ignores
->list
[i
];
1556 hi
->ignores
->list
[i
] = hi
->ignores
->list
[--hi
->ignores
->used
];
1557 reply("NSMSG_DELMASK_SUCCESS", old_mask
);
1558 for (target
= hi
->users
; target
; target
= target
->next_authed
) {
1559 irc_silence(target
, old_mask
, 0);
1566 reply("NSMSG_DELMASK_NOT_FOUND");
1570 static NICKSERV_FUNC(cmd_delignore
)
1572 NICKSERV_MIN_PARMS(2);
1573 return nickserv_delignore(cmd
, user
, user
->handle_info
, argv
[1]);
1576 static NICKSERV_FUNC(cmd_odelignore
)
1578 struct handle_info
*hi
;
1579 NICKSERV_MIN_PARMS(3);
1580 if (!(hi
= get_victim_oper(cmd
, user
, argv
[1])))
1582 return nickserv_delignore(cmd
, user
, hi
, argv
[2]);
1585 static NICKSERV_FUNC(cmd_handleinfo
)
1588 unsigned int i
, pos
=0, herelen
;
1589 struct userNode
*target
, *next_un
;
1590 struct handle_info
*hi
;
1591 const char *nsmsg_none
;
1594 if (!(hi
= user
->handle_info
)) {
1595 reply("NSMSG_MUST_AUTH");
1598 } else if (!(hi
= modcmd_get_handle_info(user
, argv
[1]))) {
1602 nsmsg_none
= handle_find_message(hi
, "MSG_NONE");
1603 reply("NSMSG_HANDLEINFO_ON", hi
->handle
);
1605 reply("NSMSG_HANDLEINFO_REGGED", ctime(&hi
->registered
));
1608 intervalString(buff
, now
- hi
->lastseen
, user
->handle_info
);
1609 reply("NSMSG_HANDLEINFO_LASTSEEN", buff
);
1611 reply("NSMSG_HANDLEINFO_LASTSEEN_NOW");
1614 reply("NSMSG_HANDLEINFO_INFOLINE", (hi
->infoline
? hi
->infoline
: nsmsg_none
));
1615 if (HANDLE_FLAGGED(hi
, FROZEN
))
1616 reply("NSMSG_HANDLEINFO_VACATION");
1618 if (oper_has_access(user
, cmd
->parent
->bot
, 0, 1)) {
1619 struct do_not_register
*dnr
;
1620 if ((dnr
= chanserv_is_dnr(NULL
, hi
)))
1621 reply("NSMSG_HANDLEINFO_DNR", dnr
->setter
, dnr
->reason
);
1622 if (!oper_outranks(cmd
, user
, hi
))
1624 } else if (hi
!= user
->handle_info
) {
1625 reply("NSMSG_HANDLEINFO_END");
1629 if (nickserv_conf
.email_enabled
)
1630 reply("NSMSG_HANDLEINFO_EMAIL_ADDR", visible_email_addr(user
, hi
));
1634 switch (hi
->cookie
->type
) {
1635 case ACTIVATION
: type
= "NSMSG_HANDLEINFO_COOKIE_ACTIVATION"; break;
1636 case PASSWORD_CHANGE
: type
= "NSMSG_HANDLEINFO_COOKIE_PASSWORD"; break;
1637 case EMAIL_CHANGE
: type
= "NSMSG_HANDLEINFO_COOKIE_EMAIL"; break;
1638 case ALLOWAUTH
: type
= "NSMSG_HANDLEINFO_COOKIE_ALLOWAUTH"; break;
1639 default: type
= "NSMSG_HANDLEINFO_COOKIE_UNKNOWN"; break;
1645 unsigned long flen
= 1;
1646 char flags
[34]; /* 32 bits possible plus '+' and '\0' */
1648 for (i
=0, flen
=1; handle_flags
[i
]; i
++)
1649 if (hi
->flags
& 1 << i
)
1650 flags
[flen
++] = handle_flags
[i
];
1652 reply("NSMSG_HANDLEINFO_FLAGS", flags
);
1654 reply("NSMSG_HANDLEINFO_FLAGS", nsmsg_none
);
1657 if (HANDLE_FLAGGED(hi
, SUPPORT_HELPER
)
1658 || HANDLE_FLAGGED(hi
, NETWORK_HELPER
)
1659 || (hi
->opserv_level
> 0)) {
1660 reply("NSMSG_HANDLEINFO_EPITHET", (hi
->epithet
? hi
->epithet
: nsmsg_none
));
1663 if (IsHelping(user
) || IsOper(user
))
1668 strftime(date
, 64, "%b %d %Y", localtime(&hi
->note
->date
));
1669 reply("NSMSG_HANDLEINFO_NOTE", hi
->note
->setter
, date
, hi
->note
->note
);
1674 reply("NSMSG_HANDLEINFO_FAKEHOST", (hi
->fakehost
? hi
->fakehost
: handle_find_message(hi
, "MSG_NONE")));
1676 if (hi
->last_quit_host
[0])
1677 reply("NSMSG_HANDLEINFO_LAST_HOST", hi
->last_quit_host
);
1679 reply("NSMSG_HANDLEINFO_LAST_HOST_UNKNOWN");
1681 if (nickserv_conf
.disable_nicks
) {
1682 /* nicks disabled; don't show anything about registered nicks */
1683 } else if (hi
->nicks
) {
1684 struct nick_info
*ni
, *next_ni
;
1685 for (ni
= hi
->nicks
; ni
; ni
= next_ni
) {
1686 herelen
= strlen(ni
->nick
);
1687 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1689 goto print_nicks_buff
;
1693 memcpy(buff
+pos
, ni
->nick
, herelen
);
1694 pos
+= herelen
; buff
[pos
++] = ' ';
1698 reply("NSMSG_HANDLEINFO_NICKS", buff
);
1703 reply("NSMSG_HANDLEINFO_NICKS", nsmsg_none
);
1706 if (hi
->masks
->used
) {
1707 for (i
=0; i
< hi
->masks
->used
; i
++) {
1708 herelen
= strlen(hi
->masks
->list
[i
]);
1709 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1711 goto print_mask_buff
;
1713 memcpy(buff
+pos
, hi
->masks
->list
[i
], herelen
);
1714 pos
+= herelen
; buff
[pos
++] = ' ';
1715 if (i
+1 == hi
->masks
->used
) {
1718 reply("NSMSG_HANDLEINFO_MASKS", buff
);
1723 reply("NSMSG_HANDLEINFO_MASKS", nsmsg_none
);
1726 if (hi
->ignores
->used
) {
1727 for (i
=0; i
< hi
->ignores
->used
; i
++) {
1728 herelen
= strlen(hi
->ignores
->list
[i
]);
1729 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1731 goto print_ignore_buff
;
1733 memcpy(buff
+pos
, hi
->ignores
->list
[i
], herelen
);
1734 pos
+= herelen
; buff
[pos
++] = ' ';
1735 if (i
+1 == hi
->ignores
->used
) {
1738 reply("NSMSG_HANDLEINFO_IGNORES", buff
);
1743 reply("NSMSG_HANDLEINFO_IGNORES", nsmsg_none
);
1747 struct userData
*channel
, *next
;
1750 for (channel
= hi
->channels
; channel
; channel
= next
) {
1751 next
= channel
->u_next
;
1752 name
= channel
->channel
->channel
->name
;
1753 herelen
= strlen(name
);
1754 if (pos
+ herelen
+ 7 > ArrayLength(buff
)) {
1756 goto print_chans_buff
;
1758 if (IsUserSuspended(channel
))
1760 pos
+= sprintf(buff
+pos
, "%s:%s ", user_level_name_from_level(channel
->access
), name
);
1764 reply("NSMSG_HANDLEINFO_CHANNELS", buff
);
1769 reply("NSMSG_HANDLEINFO_CHANNELS", nsmsg_none
);
1772 for (target
= hi
->users
; target
; target
= next_un
) {
1773 herelen
= strlen(target
->nick
);
1774 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1776 goto print_cnick_buff
;
1778 next_un
= target
->next_authed
;
1780 memcpy(buff
+pos
, target
->nick
, herelen
);
1781 pos
+= herelen
; buff
[pos
++] = ' ';
1785 reply("NSMSG_HANDLEINFO_CURRENT", buff
);
1790 reply("NSMSG_HANDLEINFO_END");
1794 static NICKSERV_FUNC(cmd_userinfo
)
1796 struct userNode
*target
;
1798 NICKSERV_MIN_PARMS(2);
1799 if (!(target
= GetUserH(argv
[1]))) {
1800 reply("MSG_NICK_UNKNOWN", argv
[1]);
1803 if (target
->handle_info
)
1804 reply("NSMSG_USERINFO_AUTHED_AS", target
->nick
, target
->handle_info
->handle
);
1806 reply("NSMSG_USERINFO_NOT_AUTHED", target
->nick
);
1810 static NICKSERV_FUNC(cmd_nickinfo
)
1812 struct nick_info
*ni
;
1814 NICKSERV_MIN_PARMS(2);
1815 if (!(ni
= get_nick_info(argv
[1]))) {
1816 reply("MSG_NICK_UNKNOWN", argv
[1]);
1819 reply("NSMSG_NICKINFO_OWNER", ni
->nick
, ni
->owner
->handle
);
1823 static NICKSERV_FUNC(cmd_rename_handle
)
1825 struct handle_info
*hi
;
1826 struct userNode
*uNode
;
1830 NICKSERV_MIN_PARMS(3);
1831 irc_strtolower(argv
[2]);
1832 if (!(hi
= get_victim_oper(cmd
, user
, argv
[1])))
1834 if (!is_valid_handle(argv
[2])) {
1835 reply("NSMSG_FAIL_RENAME", argv
[1], argv
[2]);
1838 if (get_handle_info(argv
[2])) {
1839 reply("NSMSG_HANDLE_EXISTS", argv
[2]);
1842 if(strlen(argv
[2]) > 15)
1844 reply("NMSG_HANDLE_TOLONG", argv
[2], 15);
1849 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1850 if( (rc
= ldap_rename_account(hi
->handle
, argv
[2])) != LDAP_SUCCESS
) {
1851 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
1857 dict_remove2(nickserv_handle_dict
, old_handle
= hi
->handle
, 1);
1858 hi
->handle
= strdup(argv
[2]);
1859 dict_insert(nickserv_handle_dict
, hi
->handle
, hi
);
1860 for (nn
=0; nn
<rf_list_used
; nn
++)
1861 rf_list
[nn
](hi
, old_handle
);
1863 if (nickserv_conf
.sync_log
) {
1864 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
1865 irc_rename(uNode
, hi
->handle
);
1867 SyncLog("RENAME %s %s", old_handle
, hi
->handle
);
1870 reply("NSMSG_HANDLE_CHANGED", old_handle
, hi
->handle
);
1871 global_message_args(MESSAGE_RECIPIENT_OPERS
, "NSMSG_ACCOUNT_RENAMED",
1872 user
->handle_info
->handle
, old_handle
, hi
->handle
);
1878 static failpw_func_t
*failpw_func_list
;
1879 static unsigned int failpw_func_size
= 0, failpw_func_used
= 0;
1882 reg_failpw_func(failpw_func_t func
)
1884 if (failpw_func_used
== failpw_func_size
) {
1885 if (failpw_func_size
) {
1886 failpw_func_size
<<= 1;
1887 failpw_func_list
= realloc(failpw_func_list
, failpw_func_size
*sizeof(failpw_func_t
));
1889 failpw_func_size
= 8;
1890 failpw_func_list
= malloc(failpw_func_size
*sizeof(failpw_func_t
));
1893 failpw_func_list
[failpw_func_used
++] = func
;
1897 * Return hi if the handle/pass pair matches, NULL if it doesnt.
1899 * called by nefariouses enhanced AC login-on-connect code
1902 struct handle_info
*loc_auth(char *handle
, char *password
)
1904 int pw_arg
, used
, maxlogins
;
1907 struct handle_info
*hi
;
1908 struct userNode
*other
;
1910 int ldap_result
= LDAP_SUCCESS
;
1913 hi
= dict_find(nickserv_handle_dict
, handle
, NULL
);
1917 if(nickserv_conf
.ldap_enable
) {
1918 ldap_result
= ldap_check_auth(handle
, password
);
1919 if(ldap_result
== LDAP_SUCCESS
) {
1920 /* pull the users info from ldap:
1922 * * name if available
1926 else if(ldap_result
!= LDAP_INVALID_CREDENTIALS
) {
1932 if (!checkpass(password
, hi
->passwd
)) {
1937 if(!hi
&& nickserv_conf
.ldap_enable
&& ldap_result
== LDAP_SUCCESS
&& nickserv_conf
.ldap_autocreate
) {
1938 /* user not found, but authed to ldap successfully..
1939 * create the account.
1943 /* Add a *@* mask */
1944 if(nickserv_conf
.default_hostmask
)
1947 return NULL
; /* They dont have a *@* mask so they can't loc */
1949 if(!(hi
= nickserv_register(NULL
, NULL
, handle
, password
, 0))) {
1950 return 0; /* couldn't add the user for some reason */
1954 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
1955 string_list_append(hi
->masks
, mask_canonicalized
);
1957 if(nickserv_conf
.sync_log
)
1958 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, "@", handle
);
1962 /* Still no account, so just fail out */
1967 /* We don't know the users hostname, or anything because they
1968 * havn't registered yet. So we can only allow LOC if your
1969 * account has *@* as a hostmask.
1971 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
1973 if (!strcmp(hi
->masks
->list
[ii
], "*@*"))
1982 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
1986 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
1987 for (used
= 0, other
= hi
->users
; other
; other
= other
->next_authed
) {
1988 if (++used
>= maxlogins
) {
1995 static NICKSERV_FUNC(cmd_auth
)
1997 int pw_arg
, used
, maxlogins
;
1998 struct handle_info
*hi
;
2000 struct userNode
*other
;
2002 int ldap_result
= LDAP_OTHER
;
2006 if (user
->handle_info
) {
2007 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2010 if (IsStamped(user
)) {
2011 /* Unauthenticated users might still have been stamped
2012 previously and could therefore have a hidden host;
2013 do not allow them to authenticate. */
2014 reply("NSMSG_STAMPED_AUTH");
2019 if(nickserv_conf
.ldap_enable
) {
2020 ldap_result
= ldap_check_auth(argv
[1], argv
[2]);
2021 /* Get the users email address and update it */
2022 if(ldap_result
== LDAP_SUCCESS
) {
2024 if((rc
= ldap_get_user_info(argv
[1], &email
) != LDAP_SUCCESS
))
2026 reply("NSMSG_LDAP_FAIL_EMAIL", ldap_err2string(rc
));
2030 else if(ldap_result
!= LDAP_INVALID_CREDENTIALS
) {
2031 reply("NSMSG_LDAP_FAIL", ldap_err2string(ldap_result
));
2037 hi
= dict_find(nickserv_handle_dict
, argv
[1], NULL
);
2039 } else if (argc
== 2) {
2040 if (nickserv_conf
.disable_nicks
) {
2041 if (!(hi
= get_handle_info(user
->nick
))) {
2042 reply("NSMSG_HANDLE_NOT_FOUND");
2046 /* try to look up their handle from their nick */
2047 /* TODO: handle ldap auth on nickserv style networks, too */
2048 struct nick_info
*ni
;
2049 ni
= get_nick_info(user
->nick
);
2051 reply("NSMSG_NICK_NOT_REGISTERED", user
->nick
);
2058 reply("MSG_MISSING_PARAMS", argv
[0]);
2059 svccmd_send_help_brief(user
, nickserv
, cmd
);
2064 if(nickserv_conf
.ldap_enable
&& ldap_result
== LDAP_SUCCESS
&& nickserv_conf
.ldap_autocreate
) {
2065 /* user not found, but authed to ldap successfully..
2066 * create the account.
2069 if(!(hi
= nickserv_register(user
, NULL
, argv
[1], argv
[2], 0))) {
2070 reply("NSMSG_UNABLE_TO_ADD");
2071 return 0; /* couldn't add the user for some reason */
2073 /* Add a *@* mask */
2074 if(nickserv_conf
.default_hostmask
)
2077 mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2080 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
2081 string_list_append(hi
->masks
, mask_canonicalized
);
2084 nickserv_set_email_addr(hi
, email
);
2087 if(nickserv_conf
.sync_log
)
2088 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, email
? email
: "@", user
->info
);
2092 reply("NSMSG_HANDLE_NOT_FOUND");
2098 /* Responses from here on look up the language used by the handle they asked about. */
2099 passwd
= argv
[pw_arg
];
2100 if (!valid_user_for(user
, hi
)) {
2101 if (hi
->email_addr
&& nickserv_conf
.email_enabled
)
2102 send_message_type(4, user
, cmd
->parent
->bot
,
2103 handle_find_message(hi
, "NSMSG_USE_AUTHCOOKIE"),
2106 send_message_type(4, user
, cmd
->parent
->bot
,
2107 handle_find_message(hi
, "NSMSG_HOSTMASK_INVALID"),
2109 argv
[pw_arg
] = "BADMASK";
2113 if( ( nickserv_conf
.ldap_enable
&& ldap_result
== LDAP_INVALID_CREDENTIALS
) ||
2114 ( !nickserv_conf
.ldap_enable
&& !checkpass(passwd
, hi
->passwd
) ) ) {
2116 if (!checkpass(passwd
, hi
->passwd
)) {
2119 send_message_type(4, user
, cmd
->parent
->bot
,
2120 handle_find_message(hi
, "NSMSG_PASSWORD_INVALID"));
2121 argv
[pw_arg
] = "BADPASS";
2122 for (n
=0; n
<failpw_func_used
; n
++) failpw_func_list
[n
](user
, hi
);
2123 if (nickserv_conf
.autogag_enabled
) {
2124 if (!user
->auth_policer
.params
) {
2125 user
->auth_policer
.last_req
= now
;
2126 user
->auth_policer
.params
= nickserv_conf
.auth_policer_params
;
2128 if (!policer_conforms(&user
->auth_policer
, now
, 1.0)) {
2130 hostmask
= generate_hostmask(user
, GENMASK_STRICT_HOST
|GENMASK_BYIP
|GENMASK_NO_HIDING
);
2131 log_module(NS_LOG
, LOG_INFO
, "%s auto-gagged for repeated password guessing.", hostmask
);
2132 gag_create(hostmask
, nickserv
->nick
, "Repeated password guessing.", now
+nickserv_conf
.autogag_duration
);
2134 argv
[pw_arg
] = "GAGGED";
2139 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2140 send_message_type(4, user
, cmd
->parent
->bot
,
2141 handle_find_message(hi
, "NSMSG_HANDLE_SUSPENDED"));
2142 argv
[pw_arg
] = "SUSPENDED";
2145 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
2146 for (used
= 0, other
= hi
->users
; other
; other
= other
->next_authed
) {
2147 if (++used
>= maxlogins
) {
2148 send_message_type(4, user
, cmd
->parent
->bot
,
2149 handle_find_message(hi
, "NSMSG_MAX_LOGINS"),
2151 argv
[pw_arg
] = "MAXLOGINS";
2156 set_user_handle_info(user
, hi
, 1);
2157 if (nickserv_conf
.email_required
&& !hi
->email_addr
)
2158 reply("NSMSG_PLEASE_SET_EMAIL");
2159 if (!is_secure_password(hi
->handle
, passwd
, NULL
))
2160 reply("NSMSG_WEAK_PASSWORD");
2161 if (hi
->passwd
[0] != '$')
2162 cryptpass(passwd
, hi
->passwd
);
2164 /* If a channel was waiting for this user to auth,
2165 * finish adding them */
2166 process_adduser_pending(user
);
2168 reply("NSMSG_AUTH_SUCCESS");
2171 /* Set +x if autohide is on */
2172 if(HANDLE_FLAGGED(hi
, AUTOHIDE
))
2173 irc_umode(user
, "+x");
2175 if(!IsOper(user
)) /* If they arnt already opered.. */
2177 /* Auto Oper users with Opserv access -Life4Christ 8-10-2005 */
2178 if( nickserv_conf
.auto_admin
[0] && hi
->opserv_level
>= opserv_conf_admin_level())
2180 irc_umode(user
,nickserv_conf
.auto_admin
);
2181 reply("NSMSG_AUTO_OPER_ADMIN");
2183 else if (nickserv_conf
.auto_oper
[0] && hi
->opserv_level
> 0)
2185 irc_umode(user
,nickserv_conf
.auto_oper
);
2186 reply("NSMSG_AUTO_OPER");
2190 /* Wipe out the pass for the logs */
2191 argv
[pw_arg
] = "****";
2195 static allowauth_func_t
*allowauth_func_list
;
2196 static unsigned int allowauth_func_size
= 0, allowauth_func_used
= 0;
2199 reg_allowauth_func(allowauth_func_t func
)
2201 if (allowauth_func_used
== allowauth_func_size
) {
2202 if (allowauth_func_size
) {
2203 allowauth_func_size
<<= 1;
2204 allowauth_func_list
= realloc(allowauth_func_list
, allowauth_func_size
*sizeof(allowauth_func_t
));
2206 allowauth_func_size
= 8;
2207 allowauth_func_list
= malloc(allowauth_func_size
*sizeof(allowauth_func_t
));
2210 allowauth_func_list
[allowauth_func_used
++] = func
;
2213 static NICKSERV_FUNC(cmd_allowauth
)
2215 struct userNode
*target
;
2216 struct handle_info
*hi
;
2219 NICKSERV_MIN_PARMS(2);
2220 if (!(target
= GetUserH(argv
[1]))) {
2221 reply("MSG_NICK_UNKNOWN", argv
[1]);
2224 if (target
->handle_info
) {
2225 reply("NSMSG_USER_PREV_AUTH", target
->nick
);
2228 if (IsStamped(target
)) {
2229 /* Unauthenticated users might still have been stamped
2230 previously and could therefore have a hidden host;
2231 do not allow them to authenticate to an account. */
2232 reply("NSMSG_USER_PREV_STAMP", target
->nick
);
2237 else if (!(hi
= get_handle_info(argv
[2]))) {
2238 reply("MSG_HANDLE_UNKNOWN", argv
[2]);
2242 if (hi
->opserv_level
> user
->handle_info
->opserv_level
) {
2243 reply("MSG_USER_OUTRANKED", hi
->handle
);
2246 if (((hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
))
2247 || (hi
->opserv_level
> 0))
2248 && ((argc
< 4) || irccasecmp(argv
[3], "staff"))) {
2249 reply("NSMSG_ALLOWAUTH_STAFF", hi
->handle
);
2252 dict_insert(nickserv_allow_auth_dict
, target
->nick
, hi
);
2253 reply("NSMSG_AUTH_ALLOWED", target
->nick
, hi
->handle
);
2254 send_message(target
, nickserv
, "NSMSG_AUTH_ALLOWED_MSG", hi
->handle
, hi
->handle
);
2255 if (nickserv_conf
.email_enabled
)
2256 send_message(target
, nickserv
, "NSMSG_AUTH_ALLOWED_EMAIL");
2258 if (dict_remove(nickserv_allow_auth_dict
, target
->nick
))
2259 reply("NSMSG_AUTH_NORMAL_ONLY", target
->nick
);
2261 reply("NSMSG_AUTH_UNSPECIAL", target
->nick
);
2263 for (n
=0; n
<allowauth_func_used
; n
++)
2264 allowauth_func_list
[n
](user
, target
, hi
);
2268 static NICKSERV_FUNC(cmd_authcookie
)
2270 struct handle_info
*hi
;
2272 NICKSERV_MIN_PARMS(2);
2273 if (user
->handle_info
) {
2274 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2277 if (IsStamped(user
)) {
2278 /* Unauthenticated users might still have been stamped
2279 previously and could therefore have a hidden host;
2280 do not allow them to authenticate to an account. */
2281 reply("NSMSG_STAMPED_AUTHCOOKIE");
2284 if (!(hi
= get_handle_info(argv
[1]))) {
2285 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2288 if (!hi
->email_addr
) {
2289 reply("MSG_SET_EMAIL_ADDR");
2292 nickserv_make_cookie(user
, hi
, ALLOWAUTH
, NULL
, 0);
2296 static NICKSERV_FUNC(cmd_delcookie
)
2298 struct handle_info
*hi
;
2300 hi
= user
->handle_info
;
2302 reply("NSMSG_NO_COOKIE");
2305 switch (hi
->cookie
->type
) {
2308 reply("NSMSG_MUST_TIME_OUT");
2311 nickserv_eat_cookie(hi
->cookie
);
2312 reply("NSMSG_ATE_COOKIE");
2318 static NICKSERV_FUNC(cmd_odelcookie
)
2320 struct handle_info
*hi
;
2322 NICKSERV_MIN_PARMS(2);
2324 if (!(hi
= get_victim_oper(cmd
, user
, argv
[1])))
2328 reply("NSMSG_NO_COOKIE_FOREIGN", hi
->handle
);
2332 switch (hi
->cookie
->type
) {
2334 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2335 if (nickserv_conf
.sync_log
)
2336 SyncLog("ACCOUNTACC %s", hi
->handle
);
2338 case PASSWORD_CHANGE
:
2339 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2340 if (nickserv_conf
.sync_log
)
2341 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
2344 if (!hi
->email_addr
&& nickserv_conf
.sync_log
) {
2345 if (nickserv_conf
.sync_log
)
2346 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, hi
->cookie
->data
, user
->info
);
2349 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2351 if((rc
= ldap_do_modify(hi
->handle
, NULL
, hi
->cookie
->data
)) != LDAP_SUCCESS
) {
2352 /* Falied to update email in ldap, but still
2353 * updated it here.. what should we do? */
2354 reply("NSMSG_LDAP_FAIL_EMAIL", ldap_err2string(rc
));
2356 nickserv_set_email_addr(hi
, hi
->cookie
->data
);
2360 nickserv_set_email_addr(hi
, hi
->cookie
->data
);
2363 nickserv_set_email_addr(hi
, hi
->cookie
->data
);
2365 if (nickserv_conf
.sync_log
)
2366 SyncLog("EMAILCHANGE %s %s", hi
->handle
, hi
->cookie
->data
);
2369 reply("NSMSG_BAD_COOKIE_TYPE", hi
->cookie
->type
);
2370 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d for account %s.", hi
->cookie
->type
, hi
->handle
);
2374 nickserv_eat_cookie(hi
->cookie
);
2375 reply("NSMSG_ATE_FOREIGN_COOKIE", hi
->handle
);
2380 static NICKSERV_FUNC(cmd_resetpass
)
2382 struct handle_info
*hi
;
2383 char crypted
[MD5_CRYPT_LENGTH
];
2386 NICKSERV_MIN_PARMS(3);
2387 if(argc
>= 4 && !strcmp(argv
[3], "WEBLINK"))
2391 if (user
->handle_info
) {
2392 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2395 if (IsStamped(user
)) {
2396 /* Unauthenticated users might still have been stamped
2397 previously and could therefore have a hidden host;
2398 do not allow them to activate an account. */
2399 reply("NSMSG_STAMPED_RESETPASS");
2402 if (!(hi
= get_handle_info(argv
[1]))) {
2403 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2406 if (!hi
->email_addr
) {
2407 reply("MSG_SET_EMAIL_ADDR");
2410 cryptpass(argv
[2], crypted
);
2412 nickserv_make_cookie(user
, hi
, PASSWORD_CHANGE
, crypted
, weblink
);
2416 static NICKSERV_FUNC(cmd_cookie
)
2418 struct handle_info
*hi
;
2421 if ((argc
== 2) && (hi
= user
->handle_info
) && hi
->cookie
&& (hi
->cookie
->type
== EMAIL_CHANGE
)) {
2424 NICKSERV_MIN_PARMS(3);
2425 if (!(hi
= get_handle_info(argv
[1]))) {
2426 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2432 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2433 reply("NSMSG_HANDLE_SUSPENDED");
2438 reply("NSMSG_NO_COOKIE");
2442 /* Check validity of operation before comparing cookie to
2443 * prohibit guessing by authed users. */
2444 if (user
->handle_info
2445 && (hi
->cookie
->type
!= EMAIL_CHANGE
)
2446 && (hi
->cookie
->type
!= PASSWORD_CHANGE
)) {
2447 reply("NSMSG_CANNOT_COOKIE");
2451 if (strcmp(cookie
, hi
->cookie
->cookie
)) {
2452 reply("NSMSG_BAD_COOKIE");
2456 switch (hi
->cookie
->type
) {
2458 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2459 set_user_handle_info(user
, hi
, 1);
2460 reply("NSMSG_HANDLE_ACTIVATED");
2461 if (nickserv_conf
.sync_log
)
2462 SyncLog("ACCOUNTACC %s", hi
->handle
);
2464 case PASSWORD_CHANGE
:
2465 set_user_handle_info(user
, hi
, 1);
2466 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2467 reply("NSMSG_PASSWORD_CHANGED");
2468 if (nickserv_conf
.sync_log
)
2469 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
2473 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2475 if((rc
= ldap_do_modify(hi
->handle
, NULL
, hi
->cookie
->data
)) != LDAP_SUCCESS
) {
2476 /* Falied to update email in ldap, but still
2477 * updated it here.. what should we do? */
2478 reply("NSMSG_LDAP_FAIL_EMAIL", ldap_err2string(rc
));
2483 if (!hi
->email_addr
&& nickserv_conf
.sync_log
) {
2485 * This should only happen if an OREGISTER was sent. Require
2486 * email must be enabled! - SiRVulcaN
2488 if (nickserv_conf
.sync_log
)
2489 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, hi
->cookie
->data
, user
->info
);
2492 nickserv_set_email_addr(hi
, hi
->cookie
->data
);
2493 reply("NSMSG_EMAIL_CHANGED");
2494 if (nickserv_conf
.sync_log
)
2495 SyncLog("EMAILCHANGE %s %s", hi
->handle
, hi
->cookie
->data
);
2498 set_user_handle_info(user
, hi
, 1);
2499 reply("NSMSG_AUTH_SUCCESS");
2502 reply("NSMSG_BAD_COOKIE_TYPE", hi
->cookie
->type
);
2503 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d for account %s.", hi
->cookie
->type
, hi
->handle
);
2507 nickserv_eat_cookie(hi
->cookie
);
2509 process_adduser_pending(user
);
2514 static NICKSERV_FUNC(cmd_oregnick
) {
2516 struct handle_info
*target
;
2517 struct nick_info
*ni
;
2519 NICKSERV_MIN_PARMS(3);
2520 if (!(target
= modcmd_get_handle_info(user
, argv
[1])))
2523 if (!is_registerable_nick(nick
)) {
2524 reply("NSMSG_BAD_NICK", nick
);
2527 ni
= dict_find(nickserv_nick_dict
, nick
, NULL
);
2529 reply("NSMSG_NICK_EXISTS", nick
);
2532 register_nick(nick
, target
);
2533 reply("NSMSG_OREGNICK_SUCCESS", nick
, target
->handle
);
2537 static NICKSERV_FUNC(cmd_regnick
) {
2539 struct nick_info
*ni
;
2541 if (!is_registerable_nick(user
->nick
)) {
2542 reply("NSMSG_BAD_NICK", user
->nick
);
2545 /* count their nicks, see if it's too many */
2546 for (n
=0,ni
=user
->handle_info
->nicks
; ni
; n
++,ni
=ni
->next
) ;
2547 if (n
>= nickserv_conf
.nicks_per_handle
) {
2548 reply("NSMSG_TOO_MANY_NICKS");
2551 ni
= dict_find(nickserv_nick_dict
, user
->nick
, NULL
);
2553 reply("NSMSG_NICK_EXISTS", user
->nick
);
2556 register_nick(user
->nick
, user
->handle_info
);
2557 reply("NSMSG_REGNICK_SUCCESS", user
->nick
);
2561 static NICKSERV_FUNC(cmd_pass
)
2563 struct handle_info
*hi
;
2564 char *old_pass
, *new_pass
;
2569 NICKSERV_MIN_PARMS(3);
2570 hi
= user
->handle_info
;
2574 if (!is_secure_password(hi
->handle
, new_pass
, user
)) return 0;
2577 if(nickserv_conf
.ldap_enable
) {
2578 ldap_result
= ldap_check_auth(hi
->handle
, old_pass
);
2579 if(ldap_result
!= LDAP_SUCCESS
) {
2580 if(ldap_result
== LDAP_INVALID_CREDENTIALS
)
2581 reply("NSMSG_PASSWORD_INVALID");
2583 reply("NSMSG_LDAP_FAIL", ldap_err2string(ldap_result
));
2588 if (!checkpass(old_pass
, hi
->passwd
)) {
2589 argv
[1] = "BADPASS";
2590 reply("NSMSG_PASSWORD_INVALID");
2594 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2596 if((rc
= ldap_do_modify(hi
->handle
, new_pass
, NULL
)) != LDAP_SUCCESS
) {
2597 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2602 cryptpass(new_pass
, hi
->passwd
);
2603 if (nickserv_conf
.sync_log
)
2604 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
2606 reply("NSMSG_PASS_SUCCESS");
2611 nickserv_addmask(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, const char *mask
)
2614 char *new_mask
= canonicalize_hostmask(strdup(mask
));
2615 for (i
=0; i
<hi
->masks
->used
; i
++) {
2616 if (!irccasecmp(new_mask
, hi
->masks
->list
[i
])) {
2617 reply("NSMSG_ADDMASK_ALREADY", new_mask
);
2622 string_list_append(hi
->masks
, new_mask
);
2623 reply("NSMSG_ADDMASK_SUCCESS", new_mask
);
2627 static NICKSERV_FUNC(cmd_addmask
)
2630 char *mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2631 int res
= nickserv_addmask(cmd
, user
, user
->handle_info
, mask
);
2635 if (!is_gline(argv
[1])) {
2636 reply("NSMSG_MASK_INVALID", argv
[1]);
2639 return nickserv_addmask(cmd
, user
, user
->handle_info
, argv
[1]);
2643 static NICKSERV_FUNC(cmd_oaddmask
)
2645 struct handle_info
*hi
;
2647 NICKSERV_MIN_PARMS(3);
2648 if (!(hi
= get_victim_oper(cmd
, user
, argv
[1])))
2650 return nickserv_addmask(cmd
, user
, hi
, argv
[2]);
2654 nickserv_delmask(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, const char *del_mask
)
2657 for (i
=0; i
<hi
->masks
->used
; i
++) {
2658 if (!strcmp(del_mask
, hi
->masks
->list
[i
])) {
2659 char *old_mask
= hi
->masks
->list
[i
];
2660 if (hi
->masks
->used
== 1) {
2661 reply("NSMSG_DELMASK_NOTLAST");
2664 hi
->masks
->list
[i
] = hi
->masks
->list
[--hi
->masks
->used
];
2665 reply("NSMSG_DELMASK_SUCCESS", old_mask
);
2670 reply("NSMSG_DELMASK_NOT_FOUND");
2674 static NICKSERV_FUNC(cmd_delmask
)
2676 NICKSERV_MIN_PARMS(2);
2677 return nickserv_delmask(cmd
, user
, user
->handle_info
, argv
[1]);
2680 static NICKSERV_FUNC(cmd_odelmask
)
2682 struct handle_info
*hi
;
2683 NICKSERV_MIN_PARMS(3);
2684 if (!(hi
= get_victim_oper(cmd
, user
, argv
[1])))
2686 return nickserv_delmask(cmd
, user
, hi
, argv
[2]);
2690 nickserv_modify_handle_flags(struct userNode
*user
, struct userNode
*bot
, const char *str
, unsigned long *padded
, unsigned long *premoved
) {
2691 unsigned int nn
, add
= 1, pos
;
2692 unsigned long added
, removed
, flag
;
2694 for (added
=removed
=nn
=0; str
[nn
]; nn
++) {
2696 case '+': add
= 1; break;
2697 case '-': add
= 0; break;
2699 if (!(pos
= handle_inverse_flags
[(unsigned char)str
[nn
]])) {
2700 send_message(user
, bot
, "NSMSG_INVALID_FLAG", str
[nn
]);
2703 if (user
&& (user
->handle_info
->opserv_level
< flag_access_levels
[pos
-1])) {
2704 /* cheesy avoidance of looking up the flag name.. */
2705 send_message(user
, bot
, "NSMSG_FLAG_PRIVILEGED", str
[nn
]);
2708 flag
= 1 << (pos
- 1);
2710 added
|= flag
, removed
&= ~flag
;
2712 removed
|= flag
, added
&= ~flag
;
2717 *premoved
= removed
;
2722 nickserv_apply_flags(struct userNode
*user
, struct handle_info
*hi
, const char *flags
)
2724 unsigned long before
, after
, added
, removed
;
2725 struct userNode
*uNode
;
2727 before
= hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
);
2728 if (!nickserv_modify_handle_flags(user
, nickserv
, flags
, &added
, &removed
))
2730 hi
->flags
= (hi
->flags
| added
) & ~removed
;
2731 after
= hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
);
2733 /* Strip helping flag if they're only a support helper and not
2734 * currently in #support. */
2735 if (HANDLE_FLAGGED(hi
, HELPING
) && (after
== HI_FLAG_SUPPORT_HELPER
)) {
2736 struct channelList
*schannels
;
2738 schannels
= chanserv_support_channels();
2739 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
) {
2740 for (ii
= 0; ii
< schannels
->used
; ++ii
)
2741 if (GetUserMode(schannels
->list
[ii
], uNode
))
2743 if (ii
< schannels
->used
)
2747 HANDLE_CLEAR_FLAG(hi
, HELPING
);
2750 if (after
&& !before
) {
2751 /* Add user to current helper list. */
2752 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
2753 userList_append(&curr_helpers
, uNode
);
2754 } else if (!after
&& before
) {
2755 /* Remove user from current helper list. */
2756 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
2757 userList_remove(&curr_helpers
, uNode
);
2764 set_list(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, int override
)
2768 char *set_display
[] = {
2769 "INFO", "WIDTH", "TABLEWIDTH", "COLOR", "PRIVMSG", "STYLE",
2770 "EMAIL", "ANNOUNCEMENTS", "AUTOHIDE", "MAXLOGINS", "LANGUAGE",
2771 "FAKEHOST", "TITLE", "EPITHET", "ADVANCED"
2774 reply("NSMSG_SETTING_LIST");
2775 reply("NSMSG_SETTING_LIST_HEADER");
2777 /* Do this so options are presented in a consistent order. */
2778 for (i
= 0; i
< ArrayLength(set_display
); ++i
)
2779 if ((opt
= dict_find(nickserv_opt_dict
, set_display
[i
], NULL
)))
2780 opt(cmd
, user
, hi
, override
, 0, NULL
);
2781 reply("NSMSG_SETTING_LIST_END");
2784 static NICKSERV_FUNC(cmd_set
)
2786 struct handle_info
*hi
;
2789 hi
= user
->handle_info
;
2791 set_list(cmd
, user
, hi
, 0);
2794 if (!(opt
= dict_find(nickserv_opt_dict
, argv
[1], NULL
))) {
2795 reply("NSMSG_INVALID_OPTION", argv
[1]);
2798 return opt(cmd
, user
, hi
, 0, argc
-1, argv
+1);
2801 static NICKSERV_FUNC(cmd_oset
)
2803 struct handle_info
*hi
;
2806 NICKSERV_MIN_PARMS(2);
2808 if (!(hi
= get_victim_oper(cmd
, user
, argv
[1])))
2812 set_list(cmd
, user
, hi
, 0);
2816 if (!(opt
= dict_find(nickserv_opt_dict
, argv
[2], NULL
))) {
2817 reply("NSMSG_INVALID_OPTION", argv
[2]);
2821 return opt(cmd
, user
, hi
, 1, argc
-2, argv
+2);
2824 static OPTION_FUNC(opt_info
)
2828 if ((argv
[1][0] == '*') && (argv
[1][1] == 0)) {
2830 hi
->infoline
= NULL
;
2832 hi
->infoline
= strdup(unsplit_string(argv
+1, argc
-1, NULL
));
2836 info
= hi
->infoline
? hi
->infoline
: user_find_message(user
, "MSG_NONE");
2837 reply("NSMSG_SET_INFO", info
);
2841 static OPTION_FUNC(opt_width
)
2844 hi
->screen_width
= strtoul(argv
[1], NULL
, 0);
2846 if ((hi
->screen_width
> 0) && (hi
->screen_width
< MIN_LINE_SIZE
))
2847 hi
->screen_width
= MIN_LINE_SIZE
;
2848 else if (hi
->screen_width
> MAX_LINE_SIZE
)
2849 hi
->screen_width
= MAX_LINE_SIZE
;
2851 reply("NSMSG_SET_WIDTH", hi
->screen_width
);
2855 static OPTION_FUNC(opt_tablewidth
)
2858 hi
->table_width
= strtoul(argv
[1], NULL
, 0);
2860 if ((hi
->table_width
> 0) && (hi
->table_width
< MIN_LINE_SIZE
))
2861 hi
->table_width
= MIN_LINE_SIZE
;
2862 else if (hi
->screen_width
> MAX_LINE_SIZE
)
2863 hi
->table_width
= MAX_LINE_SIZE
;
2865 reply("NSMSG_SET_TABLEWIDTH", hi
->table_width
);
2869 static OPTION_FUNC(opt_color
)
2872 if (enabled_string(argv
[1]))
2873 HANDLE_SET_FLAG(hi
, MIRC_COLOR
);
2874 else if (disabled_string(argv
[1]))
2875 HANDLE_CLEAR_FLAG(hi
, MIRC_COLOR
);
2877 reply("MSG_INVALID_BINARY", argv
[1]);
2882 reply("NSMSG_SET_COLOR", user_find_message(user
, HANDLE_FLAGGED(hi
, MIRC_COLOR
) ? "MSG_ON" : "MSG_OFF"));
2886 static OPTION_FUNC(opt_privmsg
)
2889 if (enabled_string(argv
[1]))
2890 HANDLE_SET_FLAG(hi
, USE_PRIVMSG
);
2891 else if (disabled_string(argv
[1]))
2892 HANDLE_CLEAR_FLAG(hi
, USE_PRIVMSG
);
2894 reply("MSG_INVALID_BINARY", argv
[1]);
2899 reply("NSMSG_SET_PRIVMSG", user_find_message(user
, HANDLE_FLAGGED(hi
, USE_PRIVMSG
) ? "MSG_ON" : "MSG_OFF"));
2903 static OPTION_FUNC(opt_autohide
)
2906 if (enabled_string(argv
[1]))
2907 HANDLE_SET_FLAG(hi
, AUTOHIDE
);
2908 else if (disabled_string(argv
[1]))
2909 HANDLE_CLEAR_FLAG(hi
, AUTOHIDE
);
2911 reply("MSG_INVALID_BINARY", argv
[1]);
2916 reply("NSMSG_SET_AUTOHIDE", user_find_message(user
, HANDLE_FLAGGED(hi
, AUTOHIDE
) ? "MSG_ON" : "MSG_OFF"));
2920 static OPTION_FUNC(opt_style
)
2925 if (!irccasecmp(argv
[1], "Clean"))
2926 hi
->userlist_style
= HI_STYLE_CLEAN
;
2927 else if (!irccasecmp(argv
[1], "Advanced"))
2928 hi
->userlist_style
= HI_STYLE_ADVANCED
;
2929 else if (!irccasecmp(argv
[1], "Classic"))
2930 hi
->userlist_style
= HI_STYLE_CLASSIC
;
2931 else /* Default to normal */
2932 hi
->userlist_style
= HI_STYLE_NORMAL
;
2933 } /* TODO: give error if unknow style is chosen */
2935 switch (hi
->userlist_style
) {
2936 case HI_STYLE_ADVANCED
:
2939 case HI_STYLE_CLASSIC
:
2942 case HI_STYLE_CLEAN
:
2945 case HI_STYLE_NORMAL
:
2950 reply("NSMSG_SET_STYLE", style
);
2954 static OPTION_FUNC(opt_announcements
)
2959 if (enabled_string(argv
[1]))
2960 hi
->announcements
= 'y';
2961 else if (disabled_string(argv
[1]))
2962 hi
->announcements
= 'n';
2963 else if (!strcmp(argv
[1], "?") || !irccasecmp(argv
[1], "default"))
2964 hi
->announcements
= '?';
2966 reply("NSMSG_INVALID_ANNOUNCE", argv
[1]);
2971 switch (hi
->announcements
) {
2972 case 'y': choice
= user_find_message(user
, "MSG_ON"); break;
2973 case 'n': choice
= user_find_message(user
, "MSG_OFF"); break;
2974 case '?': choice
= "default"; break;
2975 default: choice
= "unknown"; break;
2977 reply("NSMSG_SET_ANNOUNCEMENTS", choice
);
2981 static OPTION_FUNC(opt_password
)
2984 reply("NSMSG_USE_CMD_PASS");
2989 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2991 if((rc
= ldap_do_modify(hi
->handle
, argv
[1], NULL
)) != LDAP_SUCCESS
) {
2992 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2998 cryptpass(argv
[1], hi
->passwd
);
3000 if (nickserv_conf
.sync_log
)
3001 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
3003 reply("NSMSG_SET_PASSWORD", "***");
3007 static OPTION_FUNC(opt_flags
)
3010 unsigned int ii
, flen
;
3013 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3018 nickserv_apply_flags(user
, hi
, argv
[1]);
3020 for (ii
= flen
= 0; handle_flags
[ii
]; ii
++)
3021 if (hi
->flags
& (1 << ii
))
3022 flags
[flen
++] = handle_flags
[ii
];
3025 reply("NSMSG_SET_FLAGS", flags
);
3027 reply("NSMSG_SET_FLAGS", user_find_message(user
, "MSG_NONE"));
3031 static OPTION_FUNC(opt_email
)
3035 if (!valid_email(argv
[1])) {
3036 reply("NSMSG_BAD_EMAIL_ADDR");
3039 if ((str
= sendmail_prohibited_address(argv
[1]))) {
3040 reply("NSMSG_EMAIL_PROHIBITED", argv
[1], str
);
3043 if (hi
->email_addr
&& !irccasecmp(hi
->email_addr
, argv
[1]))
3044 reply("NSMSG_EMAIL_SAME");
3046 nickserv_make_cookie(user
, hi
, EMAIL_CHANGE
, argv
[1], 0);
3049 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
3051 if((rc
= ldap_do_modify(hi
->handle
, argv
[1], NULL
)) != LDAP_SUCCESS
) {
3052 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3057 nickserv_set_email_addr(hi
, argv
[1]);
3059 nickserv_eat_cookie(hi
->cookie
);
3060 reply("NSMSG_SET_EMAIL", visible_email_addr(user
, hi
));
3063 reply("NSMSG_SET_EMAIL", visible_email_addr(user
, hi
));
3067 static OPTION_FUNC(opt_maxlogins
)
3069 unsigned char maxlogins
;
3071 maxlogins
= strtoul(argv
[1], NULL
, 0);
3072 if ((maxlogins
> nickserv_conf
.hard_maxlogins
) && !override
) {
3073 reply("NSMSG_BAD_MAX_LOGINS", nickserv_conf
.hard_maxlogins
);
3076 hi
->maxlogins
= maxlogins
;
3078 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
3079 reply("NSMSG_SET_MAXLOGINS", maxlogins
);
3083 static OPTION_FUNC(opt_advanced
)
3086 if (enabled_string(argv
[1]))
3087 HANDLE_SET_FLAG(hi
, ADVANCED
);
3088 else if (disabled_string(argv
[1]))
3089 HANDLE_CLEAR_FLAG(hi
, ADVANCED
);
3091 reply("MSG_INVALID_BINARY", argv
[1]);
3096 reply("NSMSG_SET_ADVANCED", user_find_message(user
, HANDLE_FLAGGED(hi
, ADVANCED
) ? "MSG_ON" : "MSG_OFF"));
3100 static OPTION_FUNC(opt_language
)
3102 struct language
*lang
;
3104 lang
= language_find(argv
[1]);
3105 if (irccasecmp(lang
->name
, argv
[1]))
3106 reply("NSMSG_LANGUAGE_NOT_FOUND", argv
[1], lang
->name
);
3107 hi
->language
= lang
;
3109 reply("NSMSG_SET_LANGUAGE", hi
->language
->name
);
3113 /* Called from opserv from cmd_access */
3115 oper_try_set_access(struct userNode
*user
, struct userNode
*bot
, struct handle_info
*target
, unsigned int new_level
) {
3116 if (!oper_has_access(user
, bot
, nickserv_conf
.modoper_level
, 0))
3118 if ((user
->handle_info
->opserv_level
< target
->opserv_level
)
3119 || ((user
->handle_info
->opserv_level
== target
->opserv_level
)
3120 && (user
->handle_info
->opserv_level
< 1000))) {
3121 send_message(user
, bot
, "MSG_USER_OUTRANKED", target
->handle
);
3124 if ((user
->handle_info
->opserv_level
< new_level
)
3125 || ((user
->handle_info
->opserv_level
== new_level
)
3126 && (user
->handle_info
->opserv_level
< 1000))) {
3127 send_message(user
, bot
, "NSMSG_OPSERV_LEVEL_BAD");
3130 if (user
->handle_info
== target
) {
3131 send_message(user
, bot
, "MSG_STUPID_ACCESS_CHANGE");
3135 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_oper_group_dn
&& nickserv_conf
.ldap_admin_dn
) {
3138 rc
= ldap_add2group(target
->handle
, nickserv_conf
.ldap_oper_group_dn
);
3140 rc
= ldap_delfromgroup(target
->handle
, nickserv_conf
.ldap_oper_group_dn
);
3141 if(rc
!= LDAP_SUCCESS
) {
3142 send_message(user
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3147 if (target
->opserv_level
== new_level
)
3149 log_module(NS_LOG
, LOG_INFO
, "Account %s setting oper level for account %s to %d (from %d).",
3150 user
->handle_info
->handle
, target
->handle
, new_level
, target
->opserv_level
);
3151 target
->opserv_level
= new_level
;
3155 static OPTION_FUNC(opt_level
)
3160 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3164 res
= (argc
> 1) ? oper_try_set_access(user
, nickserv
, hi
, strtoul(argv
[1], NULL
, 0)) : 0;
3165 reply("NSMSG_SET_LEVEL", hi
->opserv_level
);
3169 static OPTION_FUNC(opt_epithet
)
3171 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_epithet_level
, 0)) {
3173 struct userNode
*target
, *next_un
;
3176 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3180 epithet
= unsplit_string(argv
+1, argc
-1, NULL
);
3184 if ((epithet
[0] == '*') && !epithet
[1])
3187 hi
->epithet
= strdup(epithet
);
3189 for (target
= hi
->users
; target
; target
= next_un
) {
3190 irc_swhois(nickserv
, target
, hi
->epithet
);
3192 next_un
= target
->next_authed
;
3197 reply("NSMSG_SET_EPITHET", hi
->epithet
);
3199 reply("NSMSG_SET_EPITHET", user_find_message(user
, "MSG_NONE"));
3203 static OPTION_FUNC(opt_title
)
3209 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_title_level
, 0)) {
3211 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3216 if(!strcmp(title
, "*")) {
3218 hi
->fakehost
= NULL
;
3221 if (strchr(title
, '.')) {
3222 reply("NSMSG_TITLE_INVALID");
3225 /* Alphanumeric titles only. */
3226 for(sptr
= title
; *sptr
; sptr
++) {
3227 if(!isalnum(*sptr
) && *sptr
!= '-') {
3228 reply("NSMSG_TITLE_INVALID");
3232 if ((strlen(user
->handle_info
->handle
) + strlen(title
) +
3233 strlen(nickserv_conf
.titlehost_suffix
) + 2) > HOSTLEN
) {
3234 reply("NSMSG_TITLE_TRUNCATED");
3238 hi
->fakehost
= malloc(strlen(title
)+2);
3239 hi
->fakehost
[0] = '.';
3240 strcpy(hi
->fakehost
+1, title
);
3243 } else if (hi
->fakehost
&& (hi
->fakehost
[0] == '.'))
3244 title
= hi
->fakehost
+ 1;
3246 /* If theres no title set then the default title will therefore
3247 be the first part of hidden_host in x3.conf, so for
3248 consistency with opt_fakehost we will print this here.
3249 This isnt actually used in P10, its just handled to keep from crashing... */
3250 char *hs
, *hidden_suffix
, *rest
;
3252 hs
= conf_get_data("server/hidden_host", RECDB_QSTRING
);
3253 hidden_suffix
= strdup(hs
);
3255 /* Yes we do this twice */
3256 if((rest
= strchr(hidden_suffix
, '.')))
3259 title
= hidden_suffix
;
3263 /* A lame default if someone configured hidden_host to something lame */
3264 title
= strdup("users");
3265 free(hidden_suffix
);
3271 none
= user_find_message(user
, "MSG_NONE");
3272 send_message(user
, nickserv
, "NSMSG_SET_TITLE", title
? title
: none
);
3277 check_vhost(char *vhost
, struct userNode
*user
, struct svccmd
*cmd
)
3281 // check for a dot in the vhost
3282 if(strchr(vhost
, '.') == NULL
) {
3283 reply("NSMSG_NOT_VALID_FAKEHOST_DOT", vhost
);
3287 // check for a @ in the vhost
3288 if(strchr(vhost
, '@') != NULL
) {
3289 reply("NSMSG_NOT_VALID_FAKEHOST_AT", vhost
);
3293 // check for denied words, inspired by monk at paki.sex
3294 for(y
= 0; y
< nickserv_conf
.denied_fakehost_words
->used
; y
++) {
3295 if(strstr(vhost
, nickserv_conf
.denied_fakehost_words
->list
[y
]) != NULL
) {
3296 reply("NSMSG_DENIED_FAKEHOST_WORD", vhost
, nickserv_conf
.denied_fakehost_words
->list
[y
]);
3301 // check for ircu's HOSTLEN length.
3302 if(strlen(vhost
) >= HOSTLEN
) {
3303 reply("NSMSG_NOT_VALID_FAKEHOST_LEN", vhost
);
3307 /* This can be handled by the regex now if desired.
3308 if (vhost[strspn(vhost, "0123456789.")]) {
3309 hostname = vhost + strlen(vhost);
3310 for (depth = 1; depth && (hostname > vhost); depth--) {
3312 while ((hostname > vhost) && (*hostname != '.')) hostname--;
3315 if (*hostname == '.') hostname++; * advance past last dot we saw *
3316 if(strlen(hostname) > 4) {
3317 reply("NSMSG_NOT_VALID_FAKEHOST_TLD_LEN", vhost);
3322 /* test either regex or as valid handle */
3323 if (nickserv_conf
.valid_fakehost_regex_set
) {
3324 int err
= regexec(&nickserv_conf
.valid_fakehost_regex
, vhost
, 0, 0, 0);
3327 buff
[regerror(err
, &nickserv_conf
.valid_fakehost_regex
, buff
, sizeof(buff
))] = 0;
3328 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
3330 if(err
== REG_NOMATCH
) {
3331 reply("NSMSG_NOT_VALID_FAKEHOST_REGEX", vhost
);
3340 static OPTION_FUNC(opt_fakehost
)
3344 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_fakehost_level
, 0)) {
3346 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3351 if ((strlen(fake
) > HOSTLEN
) || (fake
[0] == '.')) {
3352 reply("NSMSG_FAKEHOST_INVALID", HOSTLEN
);
3355 if (!strcmp(fake
, "*")) {
3358 hi
->fakehost
= NULL
;
3361 else if (!check_vhost(argv
[1], user
, cmd
)) {
3362 /* check_vhost takes care of error reply */
3368 hi
->fakehost
= strdup(fake
);
3371 fake
= hi
->fakehost
;
3373 fake
= generate_fakehost(hi
);
3375 /* Tell them we set the host */
3377 fake
= user_find_message(user
, "MSG_NONE");
3378 reply("NSMSG_SET_FAKEHOST", fake
);
3382 static OPTION_FUNC(opt_note
)
3385 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3390 char *text
= unsplit_string(argv
+ 1, argc
- 1, NULL
);
3395 if ((text
[0] == '*') && !text
[1])
3398 if (!(hi
->note
= nickserv_add_note(user
->handle_info
->handle
, now
, text
)))
3403 reply("NSMSG_SET_NOTE", hi
->note
? hi
->note
->note
: user_find_message(user
, "MSG_NONE"));
3407 static NICKSERV_FUNC(cmd_reclaim
)
3409 struct handle_info
*hi
;
3410 struct nick_info
*ni
;
3411 struct userNode
*victim
;
3413 NICKSERV_MIN_PARMS(2);
3414 hi
= user
->handle_info
;
3415 ni
= dict_find(nickserv_nick_dict
, argv
[1], 0);
3417 reply("NSMSG_UNKNOWN_NICK", argv
[1]);
3420 if (ni
->owner
!= user
->handle_info
) {
3421 reply("NSMSG_NOT_YOUR_NICK", ni
->nick
);
3424 victim
= GetUserH(ni
->nick
);
3426 reply("MSG_NICK_UNKNOWN", ni
->nick
);
3429 if (victim
== user
) {
3430 reply("NSMSG_NICK_USER_YOU");
3433 nickserv_reclaim(victim
, ni
, nickserv_conf
.reclaim_action
);
3434 switch (nickserv_conf
.reclaim_action
) {
3435 case RECLAIM_NONE
: reply("NSMSG_RECLAIMED_NONE"); break;
3436 case RECLAIM_WARN
: reply("NSMSG_RECLAIMED_WARN", victim
->nick
); break;
3437 case RECLAIM_SVSNICK
: reply("NSMSG_RECLAIMED_SVSNICK", victim
->nick
); break;
3438 case RECLAIM_KILL
: reply("NSMSG_RECLAIMED_KILL", victim
->nick
); break;
3443 static NICKSERV_FUNC(cmd_unregnick
)
3446 struct handle_info
*hi
;
3447 struct nick_info
*ni
;
3449 hi
= user
->handle_info
;
3450 nick
= (argc
< 2) ? user
->nick
: (const char*)argv
[1];
3451 ni
= dict_find(nickserv_nick_dict
, nick
, NULL
);
3453 reply("NSMSG_UNKNOWN_NICK", nick
);
3456 if (hi
!= ni
->owner
) {
3457 reply("NSMSG_NOT_YOUR_NICK", nick
);
3460 reply("NSMSG_UNREGNICK_SUCCESS", ni
->nick
);
3465 static NICKSERV_FUNC(cmd_ounregnick
)
3467 struct nick_info
*ni
;
3469 NICKSERV_MIN_PARMS(2);
3470 if (!(ni
= get_nick_info(argv
[1]))) {
3471 reply("NSMSG_NICK_NOT_REGISTERED", argv
[1]);
3474 if (ni
->owner
->opserv_level
>= user
->handle_info
->opserv_level
) {
3475 reply("MSG_USER_OUTRANKED", ni
->nick
);
3478 reply("NSMSG_UNREGNICK_SUCCESS", ni
->nick
);
3483 static NICKSERV_FUNC(cmd_unregister
)
3485 struct handle_info
*hi
;
3488 NICKSERV_MIN_PARMS(2);
3489 hi
= user
->handle_info
;
3492 if (checkpass(passwd
, hi
->passwd
)) {
3493 if(nickserv_unregister_handle(hi
, user
, cmd
->parent
->bot
))
3498 log_module(NS_LOG
, LOG_INFO
, "Account '%s' tried to unregister with the wrong password.", hi
->handle
);
3499 reply("NSMSG_PASSWORD_INVALID");
3504 static NICKSERV_FUNC(cmd_ounregister
)
3506 struct handle_info
*hi
;
3508 NICKSERV_MIN_PARMS(2);
3509 if (!(hi
= get_victim_oper(cmd
, user
, argv
[1])))
3511 if(nickserv_unregister_handle(hi
, user
, cmd
->parent
->bot
))
3517 static NICKSERV_FUNC(cmd_status
)
3519 if (nickserv_conf
.disable_nicks
) {
3520 reply("NSMSG_GLOBAL_STATS_NONICK",
3521 dict_size(nickserv_handle_dict
));
3523 if (user
->handle_info
) {
3525 struct nick_info
*ni
;
3526 for (ni
=user
->handle_info
->nicks
; ni
; ni
=ni
->next
) cnt
++;
3527 reply("NSMSG_HANDLE_STATS", cnt
);
3529 reply("NSMSG_HANDLE_NONE");
3531 reply("NSMSG_GLOBAL_STATS",
3532 dict_size(nickserv_handle_dict
),
3533 dict_size(nickserv_nick_dict
));
3538 static NICKSERV_FUNC(cmd_ghost
)
3540 struct userNode
*target
;
3541 char reason
[MAXLEN
];
3543 NICKSERV_MIN_PARMS(2);
3544 if (!(target
= GetUserH(argv
[1]))) {
3545 reply("MSG_NICK_UNKNOWN", argv
[1]);
3548 if (target
== user
) {
3549 reply("NSMSG_CANNOT_GHOST_SELF");
3552 if (!target
->handle_info
|| (target
->handle_info
!= user
->handle_info
)) {
3553 reply("NSMSG_CANNOT_GHOST_USER", target
->nick
);
3556 snprintf(reason
, sizeof(reason
), "Ghost kill on account %s (requested by %s).", target
->handle_info
->handle
, user
->nick
);
3557 DelUser(target
, nickserv
, 1, reason
);
3558 reply("NSMSG_GHOST_KILLED", argv
[1]);
3562 static NICKSERV_FUNC(cmd_vacation
)
3564 HANDLE_SET_FLAG(user
->handle_info
, FROZEN
);
3565 reply("NSMSG_ON_VACATION");
3570 nickserv_saxdb_write(struct saxdb_context
*ctx
) {
3572 struct handle_info
*hi
;
3575 for (it
= dict_first(nickserv_handle_dict
); it
; it
= iter_next(it
)) {
3577 saxdb_start_record(ctx
, iter_key(it
), 0);
3578 if (hi
->announcements
!= '?') {
3579 flags
[0] = hi
->announcements
;
3581 saxdb_write_string(ctx
, KEY_ANNOUNCEMENTS
, flags
);
3584 struct handle_cookie
*cookie
= hi
->cookie
;
3587 switch (cookie
->type
) {
3588 case ACTIVATION
: type
= KEY_ACTIVATION
; break;
3589 case PASSWORD_CHANGE
: type
= KEY_PASSWORD_CHANGE
; break;
3590 case EMAIL_CHANGE
: type
= KEY_EMAIL_CHANGE
; break;
3591 case ALLOWAUTH
: type
= KEY_ALLOWAUTH
; break;
3592 default: type
= NULL
; break;
3595 saxdb_start_record(ctx
, KEY_COOKIE
, 0);
3596 saxdb_write_string(ctx
, KEY_COOKIE_TYPE
, type
);
3597 saxdb_write_int(ctx
, KEY_COOKIE_EXPIRES
, cookie
->expires
);
3599 saxdb_write_string(ctx
, KEY_COOKIE_DATA
, cookie
->data
);
3600 saxdb_write_string(ctx
, KEY_COOKIE
, cookie
->cookie
);
3601 saxdb_end_record(ctx
);
3605 saxdb_write_string(ctx
, KEY_EMAIL_ADDR
, hi
->email_addr
);
3607 saxdb_write_string(ctx
, KEY_EPITHET
, hi
->epithet
);
3609 saxdb_start_record(ctx
, KEY_NOTE_NOTE
, 0);
3610 saxdb_write_string(ctx
, KEY_NOTE_SETTER
, hi
->note
->setter
);
3611 saxdb_write_int(ctx
, KEY_NOTE_DATE
, hi
->note
->date
);
3612 saxdb_write_string(ctx
, KEY_NOTE_NOTE
, hi
->note
->note
);
3613 saxdb_end_record(ctx
);
3617 saxdb_write_string(ctx
, KEY_FAKEHOST
, hi
->fakehost
);
3621 for (ii
=flen
=0; handle_flags
[ii
]; ++ii
)
3622 if (hi
->flags
& (1 << ii
))
3623 flags
[flen
++] = handle_flags
[ii
];
3625 saxdb_write_string(ctx
, KEY_FLAGS
, flags
);
3628 saxdb_write_string(ctx
, KEY_INFO
, hi
->infoline
);
3629 if (hi
->last_quit_host
[0])
3630 saxdb_write_string(ctx
, KEY_LAST_QUIT_HOST
, hi
->last_quit_host
);
3631 saxdb_write_int(ctx
, KEY_LAST_SEEN
, hi
->lastseen
);
3632 if (hi
->masks
->used
)
3633 saxdb_write_string_list(ctx
, KEY_MASKS
, hi
->masks
);
3634 if (hi
->ignores
->used
)
3635 saxdb_write_string_list(ctx
, KEY_IGNORES
, hi
->ignores
);
3637 saxdb_write_int(ctx
, KEY_MAXLOGINS
, hi
->maxlogins
);
3639 struct string_list
*slist
;
3640 struct nick_info
*ni
;
3642 slist
= alloc_string_list(nickserv_conf
.nicks_per_handle
);
3643 for (ni
= hi
->nicks
; ni
; ni
= ni
->next
) string_list_append(slist
, ni
->nick
);
3644 saxdb_write_string_list(ctx
, KEY_NICKS
, slist
);
3648 if (hi
->opserv_level
)
3649 saxdb_write_int(ctx
, KEY_OPSERV_LEVEL
, hi
->opserv_level
);
3650 if (hi
->language
!= lang_C
)
3651 saxdb_write_string(ctx
, KEY_LANGUAGE
, hi
->language
->name
);
3652 saxdb_write_string(ctx
, KEY_PASSWD
, hi
->passwd
);
3653 saxdb_write_int(ctx
, KEY_REGISTER_ON
, hi
->registered
);
3654 if (hi
->screen_width
)
3655 saxdb_write_int(ctx
, KEY_SCREEN_WIDTH
, hi
->screen_width
);
3656 if (hi
->table_width
)
3657 saxdb_write_int(ctx
, KEY_TABLE_WIDTH
, hi
->table_width
);
3658 flags
[0] = hi
->userlist_style
;
3660 saxdb_write_string(ctx
, KEY_USERLIST_STYLE
, flags
);
3661 saxdb_end_record(ctx
);
3667 static handle_merge_func_t
*handle_merge_func_list
;
3668 static unsigned int handle_merge_func_size
= 0, handle_merge_func_used
= 0;
3671 reg_handle_merge_func(handle_merge_func_t func
)
3673 if (handle_merge_func_used
== handle_merge_func_size
) {
3674 if (handle_merge_func_size
) {
3675 handle_merge_func_size
<<= 1;
3676 handle_merge_func_list
= realloc(handle_merge_func_list
, handle_merge_func_size
*sizeof(handle_merge_func_t
));
3678 handle_merge_func_size
= 8;
3679 handle_merge_func_list
= malloc(handle_merge_func_size
*sizeof(handle_merge_func_t
));
3682 handle_merge_func_list
[handle_merge_func_used
++] = func
;
3685 static NICKSERV_FUNC(cmd_merge
)
3687 struct handle_info
*hi_from
, *hi_to
;
3688 struct userNode
*last_user
;
3689 struct userData
*cList
, *cListNext
;
3690 unsigned int ii
, jj
, n
;
3692 NICKSERV_MIN_PARMS(3);
3694 if (!(hi_from
= get_victim_oper(cmd
, user
, argv
[1])))
3696 if (!(hi_to
= get_victim_oper(cmd
, user
, argv
[2])))
3698 if (hi_to
== hi_from
) {
3699 reply("NSMSG_CANNOT_MERGE_SELF", hi_to
->handle
);
3703 for (n
=0; n
<handle_merge_func_used
; n
++)
3704 handle_merge_func_list
[n
](user
, hi_to
, hi_from
);
3706 /* Append "from" handle's nicks to "to" handle's nick list. */
3708 struct nick_info
*last_ni
;
3709 for (last_ni
=hi_to
->nicks
; last_ni
->next
; last_ni
=last_ni
->next
) ;
3710 last_ni
->next
= hi_from
->nicks
;
3712 while (hi_from
->nicks
) {
3713 hi_from
->nicks
->owner
= hi_to
;
3714 hi_from
->nicks
= hi_from
->nicks
->next
;
3717 /* Merge the hostmasks. */
3718 for (ii
=0; ii
<hi_from
->masks
->used
; ii
++) {
3719 char *mask
= hi_from
->masks
->list
[ii
];
3720 for (jj
=0; jj
<hi_to
->masks
->used
; jj
++)
3721 if (match_ircglobs(hi_to
->masks
->list
[jj
], mask
))
3723 if (jj
==hi_to
->masks
->used
) /* Nothing from the "to" handle covered this mask, so add it. */
3724 string_list_append(hi_to
->masks
, strdup(mask
));
3727 /* Merge the ignores. */
3728 for (ii
=0; ii
<hi_from
->ignores
->used
; ii
++) {
3729 char *ignore
= hi_from
->ignores
->list
[ii
];
3730 for (jj
=0; jj
<hi_to
->ignores
->used
; jj
++)
3731 if (match_ircglobs(hi_to
->ignores
->list
[jj
], ignore
))
3733 if (jj
==hi_to
->ignores
->used
) /* Nothing from the "to" handle covered this mask, so add it. */
3734 string_list_append(hi_to
->ignores
, strdup(ignore
));
3737 /* Merge the lists of authed users. */
3739 for (last_user
=hi_to
->users
; last_user
->next_authed
; last_user
=last_user
->next_authed
) ;
3740 last_user
->next_authed
= hi_from
->users
;
3742 hi_to
->users
= hi_from
->users
;
3744 /* Repoint the old "from" handle's users. */
3745 for (last_user
=hi_from
->users
; last_user
; last_user
=last_user
->next_authed
) {
3746 last_user
->handle_info
= hi_to
;
3748 hi_from
->users
= NULL
;
3750 /* Merge channel userlists. */
3751 for (cList
=hi_from
->channels
; cList
; cList
=cListNext
) {
3752 struct userData
*cList2
;
3753 cListNext
= cList
->u_next
;
3754 for (cList2
=hi_to
->channels
; cList2
; cList2
=cList2
->u_next
)
3755 if (cList
->channel
== cList2
->channel
)
3757 if (cList2
&& (cList2
->access
>= cList
->access
)) {
3758 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
);
3759 /* keep cList2 in hi_to; remove cList from hi_from */
3760 del_channel_user(cList
, 1);
3763 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
);
3764 /* remove the lower-ranking cList2 from hi_to */
3765 del_channel_user(cList2
, 1);
3767 log_module(NS_LOG
, LOG_INFO
, "Merge: %s had no access in %s", hi_to
->handle
, cList
->channel
->channel
->name
);
3769 /* cList needs to be moved from hi_from to hi_to */
3770 cList
->handle
= hi_to
;
3771 /* Remove from linked list for hi_from */
3772 assert(!cList
->u_prev
);
3773 hi_from
->channels
= cList
->u_next
;
3775 cList
->u_next
->u_prev
= cList
->u_prev
;
3776 /* Add to linked list for hi_to */
3777 cList
->u_prev
= NULL
;
3778 cList
->u_next
= hi_to
->channels
;
3779 if (hi_to
->channels
)
3780 hi_to
->channels
->u_prev
= cList
;
3781 hi_to
->channels
= cList
;
3785 /* Do they get an OpServ level promotion? */
3786 if (hi_from
->opserv_level
> hi_to
->opserv_level
)
3787 hi_to
->opserv_level
= hi_from
->opserv_level
;
3789 /* What about last seen time? */
3790 if (hi_from
->lastseen
> hi_to
->lastseen
)
3791 hi_to
->lastseen
= hi_from
->lastseen
;
3793 /* Does a fakehost carry over? (This intentionally doesn't set it
3794 * for users previously attached to hi_to. They'll just have to
3797 if (hi_from
->fakehost
&& !hi_to
->fakehost
)
3798 hi_to
->fakehost
= strdup(hi_from
->fakehost
);
3800 /* Notify of success. */
3801 reply("NSMSG_HANDLES_MERGED", hi_from
->handle
, hi_to
->handle
);
3802 global_message_args(MESSAGE_RECIPIENT_OPERS
, "NSMSG_ACCOUNT_MERGED", user
->nick
,
3803 user
->handle_info
->handle
, hi_from
->handle
, hi_to
->handle
);
3805 /* Unregister the "from" handle. */
3806 nickserv_unregister_handle(hi_from
, NULL
, cmd
->parent
->bot
);
3807 /* TODO: fix it so that if the ldap delete in nickserv_unregister_handle fails,
3808 * the process isn't completed.
3814 struct nickserv_discrim
{
3815 unsigned int limit
, min_level
, max_level
;
3816 unsigned long flags_on
, flags_off
;
3817 time_t min_registered
, max_registered
;
3819 enum { SUBSET
, EXACT
, SUPERSET
, LASTQUIT
} hostmask_type
;
3820 const char *nickmask
;
3821 const char *hostmask
;
3822 const char *handlemask
;
3823 const char *emailmask
;
3826 typedef void (*discrim_search_func
)(struct userNode
*source
, struct handle_info
*hi
);
3828 struct discrim_apply_info
{
3829 struct nickserv_discrim
*discrim
;
3830 discrim_search_func func
;
3831 struct userNode
*source
;
3832 unsigned int matched
;
3835 static struct nickserv_discrim
*
3836 nickserv_discrim_create(struct svccmd
*cmd
, struct userNode
*user
, unsigned int argc
, char *argv
[])
3839 struct nickserv_discrim
*discrim
;
3841 discrim
= malloc(sizeof(*discrim
));
3842 memset(discrim
, 0, sizeof(*discrim
));
3843 discrim
->min_level
= 0;
3844 discrim
->max_level
= ~0;
3845 discrim
->limit
= 50;
3846 discrim
->min_registered
= 0;
3847 discrim
->max_registered
= INT_MAX
;
3848 discrim
->lastseen
= now
;
3850 for (i
=0; i
<argc
; i
++) {
3851 if (i
== argc
- 1) {
3852 reply("MSG_MISSING_PARAMS", argv
[i
]);
3855 if (!irccasecmp(argv
[i
], "limit")) {
3856 discrim
->limit
= strtoul(argv
[++i
], NULL
, 0);
3857 } else if (!irccasecmp(argv
[i
], "flags")) {
3858 nickserv_modify_handle_flags(user
, nickserv
, argv
[++i
], &discrim
->flags_on
, &discrim
->flags_off
);
3859 } else if (!irccasecmp(argv
[i
], "registered")) {
3860 const char *cmp
= argv
[++i
];
3861 if (cmp
[0] == '<') {
3862 if (cmp
[1] == '=') {
3863 discrim
->min_registered
= now
- ParseInterval(cmp
+2);
3865 discrim
->min_registered
= now
- ParseInterval(cmp
+1) + 1;
3867 } else if (cmp
[0] == '=') {
3868 discrim
->min_registered
= discrim
->max_registered
= now
- ParseInterval(cmp
+1);
3869 } else if (cmp
[0] == '>') {
3870 if (cmp
[1] == '=') {
3871 discrim
->max_registered
= now
- ParseInterval(cmp
+2);
3873 discrim
->max_registered
= now
- ParseInterval(cmp
+1) - 1;
3876 reply("MSG_INVALID_CRITERIA", cmp
);
3878 } else if (!irccasecmp(argv
[i
], "seen")) {
3879 discrim
->lastseen
= now
- ParseInterval(argv
[++i
]);
3880 } else if (!nickserv_conf
.disable_nicks
&& !irccasecmp(argv
[i
], "nickmask")) {
3881 discrim
->nickmask
= argv
[++i
];
3882 } else if (!irccasecmp(argv
[i
], "hostmask")) {
3884 if (!irccasecmp(argv
[i
], "exact")) {
3885 if (i
== argc
- 1) {
3886 reply("MSG_MISSING_PARAMS", argv
[i
]);
3889 discrim
->hostmask_type
= EXACT
;
3890 } else if (!irccasecmp(argv
[i
], "subset")) {
3891 if (i
== argc
- 1) {
3892 reply("MSG_MISSING_PARAMS", argv
[i
]);
3895 discrim
->hostmask_type
= SUBSET
;
3896 } else if (!irccasecmp(argv
[i
], "superset")) {
3897 if (i
== argc
- 1) {
3898 reply("MSG_MISSING_PARAMS", argv
[i
]);
3901 discrim
->hostmask_type
= SUPERSET
;
3902 } else if (!irccasecmp(argv
[i
], "lastquit") || !irccasecmp(argv
[i
], "lastauth")) {
3903 if (i
== argc
- 1) {
3904 reply("MSG_MISSING_PARAMS", argv
[i
]);
3907 discrim
->hostmask_type
= LASTQUIT
;
3910 discrim
->hostmask_type
= SUPERSET
;
3912 discrim
->hostmask
= argv
[++i
];
3913 } else if (!irccasecmp(argv
[i
], "handlemask") || !irccasecmp(argv
[i
], "accountmask")) {
3914 if (!irccasecmp(argv
[++i
], "*")) {
3915 discrim
->handlemask
= 0;
3917 discrim
->handlemask
= argv
[i
];
3919 } else if (!irccasecmp(argv
[i
], "email")) {
3920 if (user
->handle_info
->opserv_level
< nickserv_conf
.email_search_level
) {
3921 reply("MSG_NO_SEARCH_ACCESS", "email");
3923 } else if (!irccasecmp(argv
[++i
], "*")) {
3924 discrim
->emailmask
= 0;
3926 discrim
->emailmask
= argv
[i
];
3928 } else if (!irccasecmp(argv
[i
], "access")) {
3929 const char *cmp
= argv
[++i
];
3930 if (cmp
[0] == '<') {
3931 if (discrim
->min_level
== 0) discrim
->min_level
= 1;
3932 if (cmp
[1] == '=') {
3933 discrim
->max_level
= strtoul(cmp
+2, NULL
, 0);
3935 discrim
->max_level
= strtoul(cmp
+1, NULL
, 0) - 1;
3937 } else if (cmp
[0] == '=') {
3938 discrim
->min_level
= discrim
->max_level
= strtoul(cmp
+1, NULL
, 0);
3939 } else if (cmp
[0] == '>') {
3940 if (cmp
[1] == '=') {
3941 discrim
->min_level
= strtoul(cmp
+2, NULL
, 0);
3943 discrim
->min_level
= strtoul(cmp
+1, NULL
, 0) + 1;
3946 reply("MSG_INVALID_CRITERIA", cmp
);
3949 reply("MSG_INVALID_CRITERIA", argv
[i
]);
3960 nickserv_discrim_match(struct nickserv_discrim
*discrim
, struct handle_info
*hi
)
3962 if (((discrim
->flags_on
& hi
->flags
) != discrim
->flags_on
)
3963 || (discrim
->flags_off
& hi
->flags
)
3964 || (discrim
->min_registered
> hi
->registered
)
3965 || (discrim
->max_registered
< hi
->registered
)
3966 || (discrim
->lastseen
< (hi
->users
?now
:hi
->lastseen
))
3967 || (discrim
->handlemask
&& !match_ircglob(hi
->handle
, discrim
->handlemask
))
3968 || (discrim
->emailmask
&& (!hi
->email_addr
|| !match_ircglob(hi
->email_addr
, discrim
->emailmask
)))
3969 || (discrim
->min_level
> hi
->opserv_level
)
3970 || (discrim
->max_level
< hi
->opserv_level
)) {
3973 if (discrim
->hostmask
) {
3975 for (i
=0; i
<hi
->masks
->used
; i
++) {
3976 const char *mask
= hi
->masks
->list
[i
];
3977 if ((discrim
->hostmask_type
== SUBSET
)
3978 && (match_ircglobs(discrim
->hostmask
, mask
))) break;
3979 else if ((discrim
->hostmask_type
== EXACT
)
3980 && !irccasecmp(discrim
->hostmask
, mask
)) break;
3981 else if ((discrim
->hostmask_type
== SUPERSET
)
3982 && (match_ircglobs(mask
, discrim
->hostmask
))) break;
3983 else if ((discrim
->hostmask_type
== LASTQUIT
)
3984 && (match_ircglobs(discrim
->hostmask
, hi
->last_quit_host
))) break;
3986 if (i
==hi
->masks
->used
) return 0;
3988 if (discrim
->nickmask
) {
3989 struct nick_info
*nick
= hi
->nicks
;
3991 if (match_ircglob(nick
->nick
, discrim
->nickmask
)) break;
3994 if (!nick
) return 0;
4000 nickserv_discrim_search(struct nickserv_discrim
*discrim
, discrim_search_func dsf
, struct userNode
*source
)
4002 dict_iterator_t it
, next
;
4003 unsigned int matched
;
4005 for (it
= dict_first(nickserv_handle_dict
), matched
= 0;
4006 it
&& (matched
< discrim
->limit
);
4008 next
= iter_next(it
);
4009 if (nickserv_discrim_match(discrim
, iter_data(it
))) {
4010 dsf(source
, iter_data(it
));
4018 search_print_func(struct userNode
*source
, struct handle_info
*match
)
4020 send_message(source
, nickserv
, "NSMSG_SEARCH_MATCH", match
->handle
);
4024 search_count_func(UNUSED_ARG(struct userNode
*source
), UNUSED_ARG(struct handle_info
*match
))
4029 search_unregister_func (struct userNode
*source
, struct handle_info
*match
)
4031 if (oper_has_access(source
, nickserv
, match
->opserv_level
, 0))
4032 nickserv_unregister_handle(match
, source
, nickserv
); // XXX nickserv hard coded
4036 nickserv_sort_accounts_by_access(const void *a
, const void *b
)
4038 const struct handle_info
*hi_a
= *(const struct handle_info
**)a
;
4039 const struct handle_info
*hi_b
= *(const struct handle_info
**)b
;
4040 if (hi_a
->opserv_level
!= hi_b
->opserv_level
)
4041 return hi_b
->opserv_level
- hi_a
->opserv_level
;
4042 return irccasecmp(hi_a
->handle
, hi_b
->handle
);
4046 nickserv_show_oper_accounts(struct userNode
*user
, struct svccmd
*cmd
)
4048 struct handle_info_list hil
;
4049 struct helpfile_table tbl
;
4054 memset(&hil
, 0, sizeof(hil
));
4055 for (it
= dict_first(nickserv_handle_dict
); it
; it
= iter_next(it
)) {
4056 struct handle_info
*hi
= iter_data(it
);
4057 if (hi
->opserv_level
)
4058 handle_info_list_append(&hil
, hi
);
4060 qsort(hil
.list
, hil
.used
, sizeof(hil
.list
[0]), nickserv_sort_accounts_by_access
);
4061 tbl
.length
= hil
.used
+ 1;
4063 tbl
.flags
= TABLE_NO_FREE
| TABLE_REPEAT_ROWS
| TABLE_REPEAT_HEADERS
;
4064 tbl
.contents
= malloc(tbl
.length
* sizeof(tbl
.contents
[0]));
4065 tbl
.contents
[0] = ary
= malloc(tbl
.width
* sizeof(ary
[0]));
4068 for (ii
= 0; ii
< hil
.used
; ) {
4069 ary
= malloc(tbl
.width
* sizeof(ary
[0]));
4070 ary
[0] = hil
.list
[ii
]->handle
;
4071 ary
[1] = strtab(hil
.list
[ii
]->opserv_level
);
4072 tbl
.contents
[++ii
] = ary
;
4074 table_send(cmd
->parent
->bot
, user
->nick
, 0, NULL
, tbl
);
4075 /*reply("MSG_MATCH_COUNT", hil.used); */
4076 for (ii
= 0; ii
< hil
.used
; ii
++)
4077 free(tbl
.contents
[ii
]);
4082 static NICKSERV_FUNC(cmd_search
)
4084 struct nickserv_discrim
*discrim
;
4085 discrim_search_func action
;
4086 struct svccmd
*subcmd
;
4087 unsigned int matches
;
4090 NICKSERV_MIN_PARMS(3);
4091 sprintf(buf
, "search %s", argv
[1]);
4092 subcmd
= dict_find(nickserv_service
->commands
, buf
, NULL
);
4093 if (!irccasecmp(argv
[1], "print"))
4094 action
= search_print_func
;
4095 else if (!irccasecmp(argv
[1], "count"))
4096 action
= search_count_func
;
4097 else if (!irccasecmp(argv
[1], "unregister"))
4098 action
= search_unregister_func
;
4100 reply("NSMSG_INVALID_ACTION", argv
[1]);
4104 if (subcmd
&& !svccmd_can_invoke(user
, nickserv
, subcmd
, NULL
, SVCCMD_NOISY
))
4107 discrim
= nickserv_discrim_create(cmd
, user
, argc
-2, argv
+2);
4111 if (action
== search_print_func
)
4112 reply("NSMSG_ACCOUNT_SEARCH_RESULTS");
4113 else if (action
== search_count_func
)
4114 discrim
->limit
= INT_MAX
;
4116 matches
= nickserv_discrim_search(discrim
, action
, user
);
4119 reply("MSG_MATCH_COUNT", matches
);
4121 reply("MSG_NO_MATCHES");
4127 static MODCMD_FUNC(cmd_checkpass
)
4129 struct handle_info
*hi
;
4131 NICKSERV_MIN_PARMS(3);
4132 if (!(hi
= get_handle_info(argv
[1]))) {
4133 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
4136 if (checkpass(argv
[2], hi
->passwd
))
4137 reply("CHECKPASS_YES");
4139 reply("CHECKPASS_NO");
4145 nickserv_db_read_handle(char *handle
, dict_t obj
)
4148 struct string_list
*masks
, *slist
, *ignores
;
4149 struct handle_info
*hi
;
4150 struct userNode
*authed_users
;
4151 struct userData
*channels
;
4152 unsigned long int id
;
4155 char *setter
, *note
;
4158 str
= database_get_data(obj
, KEY_ID
, RECDB_QSTRING
);
4159 id
= str
? strtoul(str
, NULL
, 0) : 0;
4160 str
= database_get_data(obj
, KEY_PASSWD
, RECDB_QSTRING
);
4162 log_module(NS_LOG
, LOG_WARNING
, "did not find a password for %s -- skipping user.", handle
);
4165 if ((hi
= get_handle_info(handle
))) {
4166 authed_users
= hi
->users
;
4167 channels
= hi
->channels
;
4169 hi
->channels
= NULL
;
4170 dict_remove(nickserv_handle_dict
, hi
->handle
);
4172 authed_users
= NULL
;
4175 irc_strtolower(handle
);
4176 hi
= register_handle(handle
, str
, id
);
4178 hi
->users
= authed_users
;
4179 while (authed_users
) {
4180 authed_users
->handle_info
= hi
;
4181 authed_users
= authed_users
->next_authed
;
4184 hi
->channels
= channels
;
4185 masks
= database_get_data(obj
, KEY_MASKS
, RECDB_STRING_LIST
);
4186 hi
->masks
= masks
? string_list_copy(masks
) : alloc_string_list(1);
4187 ignores
= database_get_data(obj
, KEY_IGNORES
, RECDB_STRING_LIST
);
4188 hi
->ignores
= ignores
? string_list_copy(ignores
) : alloc_string_list(1);
4189 str
= database_get_data(obj
, KEY_MAXLOGINS
, RECDB_QSTRING
);
4190 hi
->maxlogins
= str
? strtoul(str
, NULL
, 0) : 0;
4191 str
= database_get_data(obj
, KEY_LANGUAGE
, RECDB_QSTRING
);
4192 hi
->language
= language_find(str
? str
: "C");
4193 str
= database_get_data(obj
, KEY_OPSERV_LEVEL
, RECDB_QSTRING
);
4194 hi
->opserv_level
= str
? strtoul(str
, NULL
, 0) : 0;
4195 str
= database_get_data(obj
, KEY_INFO
, RECDB_QSTRING
);
4197 hi
->infoline
= strdup(str
);
4198 str
= database_get_data(obj
, KEY_REGISTER_ON
, RECDB_QSTRING
);
4199 hi
->registered
= str
? (time_t)strtoul(str
, NULL
, 0) : now
;
4200 str
= database_get_data(obj
, KEY_LAST_SEEN
, RECDB_QSTRING
);
4201 hi
->lastseen
= str
? (time_t)strtoul(str
, NULL
, 0) : hi
->registered
;
4202 /* We want to read the nicks even if disable_nicks is set. This is so
4203 * that we don't lose the nick data entirely. */
4204 slist
= database_get_data(obj
, KEY_NICKS
, RECDB_STRING_LIST
);
4206 for (ii
=0; ii
<slist
->used
; ii
++)
4207 register_nick(slist
->list
[ii
], hi
);
4209 str
= database_get_data(obj
, KEY_FLAGS
, RECDB_QSTRING
);
4211 for (ii
=0; str
[ii
]; ii
++)
4212 hi
->flags
|= 1 << (handle_inverse_flags
[(unsigned char)str
[ii
]] - 1);
4214 str
= database_get_data(obj
, KEY_USERLIST_STYLE
, RECDB_QSTRING
);
4215 hi
->userlist_style
= str
? str
[0] : HI_DEFAULT_STYLE
;
4216 str
= database_get_data(obj
, KEY_ANNOUNCEMENTS
, RECDB_QSTRING
);
4217 hi
->announcements
= str
? str
[0] : '?';
4218 str
= database_get_data(obj
, KEY_SCREEN_WIDTH
, RECDB_QSTRING
);
4219 hi
->screen_width
= str
? strtoul(str
, NULL
, 0) : 0;
4220 str
= database_get_data(obj
, KEY_TABLE_WIDTH
, RECDB_QSTRING
);
4221 hi
->table_width
= str
? strtoul(str
, NULL
, 0) : 0;
4222 str
= database_get_data(obj
, KEY_LAST_QUIT_HOST
, RECDB_QSTRING
);
4224 str
= database_get_data(obj
, KEY_LAST_AUTHED_HOST
, RECDB_QSTRING
);
4226 safestrncpy(hi
->last_quit_host
, str
, sizeof(hi
->last_quit_host
));
4227 str
= database_get_data(obj
, KEY_EMAIL_ADDR
, RECDB_QSTRING
);
4229 nickserv_set_email_addr(hi
, str
);
4230 str
= database_get_data(obj
, KEY_EPITHET
, RECDB_QSTRING
);
4232 hi
->epithet
= strdup(str
);
4233 subdb
= database_get_data(obj
, KEY_NOTE_NOTE
, RECDB_OBJECT
);
4235 setter
= database_get_data(subdb
, KEY_NOTE_SETTER
, RECDB_QSTRING
);
4236 str
= database_get_data(subdb
, KEY_NOTE_DATE
, RECDB_QSTRING
);
4237 date
= str
? (time_t)strtoul(str
, NULL
, 0) : now
;
4238 note
= database_get_data(subdb
, KEY_NOTE_NOTE
, RECDB_QSTRING
);
4239 if (setter
&& date
&& note
)
4241 if (!(hi
->note
= nickserv_add_note(setter
, date
, note
)))
4246 str
= database_get_data(obj
, KEY_FAKEHOST
, RECDB_QSTRING
);
4248 hi
->fakehost
= strdup(str
);
4250 subdb
= database_get_data(obj
, KEY_COOKIE
, RECDB_OBJECT
);
4252 const char *data
, *type
, *expires
, *cookie_str
;
4253 struct handle_cookie
*cookie
;
4255 cookie
= calloc(1, sizeof(*cookie
));
4256 type
= database_get_data(subdb
, KEY_COOKIE_TYPE
, RECDB_QSTRING
);
4257 data
= database_get_data(subdb
, KEY_COOKIE_DATA
, RECDB_QSTRING
);
4258 expires
= database_get_data(subdb
, KEY_COOKIE_EXPIRES
, RECDB_QSTRING
);
4259 cookie_str
= database_get_data(subdb
, KEY_COOKIE
, RECDB_QSTRING
);
4260 if (!type
|| !expires
|| !cookie_str
) {
4261 log_module(NS_LOG
, LOG_ERROR
, "Missing field(s) from cookie for account %s; dropping cookie.", hi
->handle
);
4264 if (!irccasecmp(type
, KEY_ACTIVATION
))
4265 cookie
->type
= ACTIVATION
;
4266 else if (!irccasecmp(type
, KEY_PASSWORD_CHANGE
))
4267 cookie
->type
= PASSWORD_CHANGE
;
4268 else if (!irccasecmp(type
, KEY_EMAIL_CHANGE
))
4269 cookie
->type
= EMAIL_CHANGE
;
4270 else if (!irccasecmp(type
, KEY_ALLOWAUTH
))
4271 cookie
->type
= ALLOWAUTH
;
4273 log_module(NS_LOG
, LOG_ERROR
, "Invalid cookie type %s for account %s; dropping cookie.", type
, handle
);
4276 cookie
->expires
= strtoul(expires
, NULL
, 0);
4277 if (cookie
->expires
< now
)
4280 cookie
->data
= strdup(data
);
4281 safestrncpy(cookie
->cookie
, cookie_str
, sizeof(cookie
->cookie
));
4285 nickserv_bake_cookie(cookie
);
4287 nickserv_free_cookie(cookie
);
4292 nickserv_saxdb_read(dict_t db
) {
4294 struct record_data
*rd
;
4297 for (it
=dict_first(db
); it
; it
=iter_next(it
)) {
4299 handle
= strdup(iter_key(it
));
4300 nickserv_db_read_handle(handle
, rd
->d
.object
);
4306 static NICKSERV_FUNC(cmd_mergedb
)
4308 struct timeval start
, stop
;
4311 NICKSERV_MIN_PARMS(2);
4312 gettimeofday(&start
, NULL
);
4313 if (!(db
= parse_database(argv
[1]))) {
4314 reply("NSMSG_DB_UNREADABLE", argv
[1]);
4317 nickserv_saxdb_read(db
);
4319 gettimeofday(&stop
, NULL
);
4320 stop
.tv_sec
-= start
.tv_sec
;
4321 stop
.tv_usec
-= start
.tv_usec
;
4322 if (stop
.tv_usec
< 0) {
4324 stop
.tv_usec
+= 1000000;
4326 reply("NSMSG_DB_MERGED", argv
[1], stop
.tv_sec
, stop
.tv_usec
/1000);
4331 expire_handles(UNUSED_ARG(void *data
))
4333 dict_iterator_t it
, next
;
4335 struct handle_info
*hi
;
4337 for (it
=dict_first(nickserv_handle_dict
); it
; it
=next
) {
4338 next
= iter_next(it
);
4340 if ((hi
->opserv_level
> 0)
4342 || HANDLE_FLAGGED(hi
, FROZEN
)
4343 || HANDLE_FLAGGED(hi
, NODELETE
)) {
4346 expiry
= hi
->channels
? nickserv_conf
.handle_expire_delay
: nickserv_conf
.nochan_handle_expire_delay
;
4347 if ((now
- hi
->lastseen
) > expiry
) {
4348 log_module(NS_LOG
, LOG_INFO
, "Expiring account %s for inactivity.", hi
->handle
);
4349 nickserv_unregister_handle(hi
, NULL
, NULL
);
4353 if (nickserv_conf
.handle_expire_frequency
)
4354 timeq_add(now
+ nickserv_conf
.handle_expire_frequency
, expire_handles
, NULL
);
4358 nickserv_load_dict(const char *fname
)
4362 if (!(file
= fopen(fname
, "r"))) {
4363 log_module(NS_LOG
, LOG_ERROR
, "Unable to open dictionary file %s: %s", fname
, strerror(errno
));
4366 while (!feof(file
)) {
4367 fgets(line
, sizeof(line
), file
);
4370 if (line
[strlen(line
)-1] == '\n')
4371 line
[strlen(line
)-1] = 0;
4372 dict_insert(nickserv_conf
.weak_password_dict
, strdup(line
), NULL
);
4375 log_module(NS_LOG
, LOG_INFO
, "Loaded %d words into weak password dictionary.", dict_size(nickserv_conf
.weak_password_dict
));
4378 static enum reclaim_action
4379 reclaim_action_from_string(const char *str
) {
4381 return RECLAIM_NONE
;
4382 else if (!irccasecmp(str
, "warn"))
4383 return RECLAIM_WARN
;
4384 else if (!irccasecmp(str
, "svsnick"))
4385 return RECLAIM_SVSNICK
;
4386 else if (!irccasecmp(str
, "kill"))
4387 return RECLAIM_KILL
;
4389 return RECLAIM_NONE
;
4393 nickserv_conf_read(void)
4395 dict_t conf_node
, child
;
4398 struct string_list
*strlist
;
4400 if (!(conf_node
= conf_get_data(NICKSERV_CONF_NAME
, RECDB_OBJECT
))) {
4401 log_module(NS_LOG
, LOG_ERROR
, "config node `%s' is missing or has wrong type.", NICKSERV_CONF_NAME
);
4404 str
= database_get_data(conf_node
, KEY_VALID_HANDLE_REGEX
, RECDB_QSTRING
);
4406 str
= database_get_data(conf_node
, KEY_VALID_ACCOUNT_REGEX
, RECDB_QSTRING
);
4407 if (nickserv_conf
.valid_handle_regex_set
)
4408 regfree(&nickserv_conf
.valid_handle_regex
);
4410 int err
= regcomp(&nickserv_conf
.valid_handle_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
4411 nickserv_conf
.valid_handle_regex_set
= !err
;
4412 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_account_regex (error %d)", err
);
4414 nickserv_conf
.valid_handle_regex_set
= 0;
4416 str
= database_get_data(conf_node
, KEY_VALID_NICK_REGEX
, RECDB_QSTRING
);
4417 if (nickserv_conf
.valid_nick_regex_set
)
4418 regfree(&nickserv_conf
.valid_nick_regex
);
4420 int err
= regcomp(&nickserv_conf
.valid_nick_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
4421 nickserv_conf
.valid_nick_regex_set
= !err
;
4422 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_nick_regex (error %d)", err
);
4424 nickserv_conf
.valid_nick_regex_set
= 0;
4426 str
= database_get_data(conf_node
, KEY_VALID_FAKEHOST_REGEX
, RECDB_QSTRING
);
4427 if (nickserv_conf
.valid_fakehost_regex_set
)
4428 regfree(&nickserv_conf
.valid_fakehost_regex
);
4430 int err
= regcomp(&nickserv_conf
.valid_fakehost_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
4431 nickserv_conf
.valid_fakehost_regex_set
= !err
;
4432 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_fakehost_regex (error %d)", err
);
4434 nickserv_conf
.valid_fakehost_regex_set
= 0;
4436 str
= database_get_data(conf_node
, KEY_NICKS_PER_HANDLE
, RECDB_QSTRING
);
4438 str
= database_get_data(conf_node
, KEY_NICKS_PER_ACCOUNT
, RECDB_QSTRING
);
4439 nickserv_conf
.nicks_per_handle
= str
? strtoul(str
, NULL
, 0) : 4;
4440 str
= database_get_data(conf_node
, KEY_DISABLE_NICKS
, RECDB_QSTRING
);
4441 nickserv_conf
.disable_nicks
= str
? strtoul(str
, NULL
, 0) : 0;
4442 str
= database_get_data(conf_node
, KEY_DEFAULT_HOSTMASK
, RECDB_QSTRING
);
4443 nickserv_conf
.default_hostmask
= str
? !disabled_string(str
) : 0;
4444 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_LENGTH
, RECDB_QSTRING
);
4445 nickserv_conf
.password_min_length
= str
? strtoul(str
, NULL
, 0) : 0;
4446 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_DIGITS
, RECDB_QSTRING
);
4447 nickserv_conf
.password_min_digits
= str
? strtoul(str
, NULL
, 0) : 0;
4448 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_UPPER
, RECDB_QSTRING
);
4449 nickserv_conf
.password_min_upper
= str
? strtoul(str
, NULL
, 0) : 0;
4450 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_LOWER
, RECDB_QSTRING
);
4451 nickserv_conf
.password_min_lower
= str
? strtoul(str
, NULL
, 0) : 0;
4452 str
= database_get_data(conf_node
, KEY_DB_BACKUP_FREQ
, RECDB_QSTRING
);
4453 nickserv_conf
.db_backup_frequency
= str
? ParseInterval(str
) : 7200;
4454 str
= database_get_data(conf_node
, KEY_MODOPER_LEVEL
, RECDB_QSTRING
);
4455 nickserv_conf
.modoper_level
= str
? strtoul(str
, NULL
, 0) : 900;
4456 str
= database_get_data(conf_node
, KEY_SET_EPITHET_LEVEL
, RECDB_QSTRING
);
4457 nickserv_conf
.set_epithet_level
= str
? strtoul(str
, NULL
, 0) : 1;
4458 str
= database_get_data(conf_node
, KEY_SET_TITLE_LEVEL
, RECDB_QSTRING
);
4459 nickserv_conf
.set_title_level
= str
? strtoul(str
, NULL
, 0) : 900;
4460 str
= database_get_data(conf_node
, KEY_SET_FAKEHOST_LEVEL
, RECDB_QSTRING
);
4461 nickserv_conf
.set_fakehost_level
= str
? strtoul(str
, NULL
, 0) : 1000;
4462 str
= database_get_data(conf_node
, KEY_HANDLE_EXPIRE_FREQ
, RECDB_QSTRING
);
4464 str
= database_get_data(conf_node
, KEY_ACCOUNT_EXPIRE_FREQ
, RECDB_QSTRING
);
4465 nickserv_conf
.handle_expire_frequency
= str
? ParseInterval(str
) : 86400;
4466 str
= database_get_data(conf_node
, KEY_HANDLE_EXPIRE_DELAY
, RECDB_QSTRING
);
4468 str
= database_get_data(conf_node
, KEY_ACCOUNT_EXPIRE_DELAY
, RECDB_QSTRING
);
4469 nickserv_conf
.handle_expire_delay
= str
? ParseInterval(str
) : 86400*30;
4470 str
= database_get_data(conf_node
, KEY_NOCHAN_HANDLE_EXPIRE_DELAY
, RECDB_QSTRING
);
4472 str
= database_get_data(conf_node
, KEY_NOCHAN_ACCOUNT_EXPIRE_DELAY
, RECDB_QSTRING
);
4473 nickserv_conf
.nochan_handle_expire_delay
= str
? ParseInterval(str
) : 86400*15;
4474 str
= database_get_data(conf_node
, "warn_clone_auth", RECDB_QSTRING
);
4475 nickserv_conf
.warn_clone_auth
= str
? !disabled_string(str
) : 1;
4476 str
= database_get_data(conf_node
, "default_maxlogins", RECDB_QSTRING
);
4477 nickserv_conf
.default_maxlogins
= str
? strtoul(str
, NULL
, 0) : 2;
4478 str
= database_get_data(conf_node
, "hard_maxlogins", RECDB_QSTRING
);
4479 nickserv_conf
.hard_maxlogins
= str
? strtoul(str
, NULL
, 0) : 10;
4480 if (!nickserv_conf
.disable_nicks
) {
4481 str
= database_get_data(conf_node
, "reclaim_action", RECDB_QSTRING
);
4482 nickserv_conf
.reclaim_action
= str
? reclaim_action_from_string(str
) : RECLAIM_NONE
;
4483 str
= database_get_data(conf_node
, "warn_nick_owned", RECDB_QSTRING
);
4484 nickserv_conf
.warn_nick_owned
= str
? enabled_string(str
) : 0;
4485 str
= database_get_data(conf_node
, "auto_reclaim_action", RECDB_QSTRING
);
4486 nickserv_conf
.auto_reclaim_action
= str
? reclaim_action_from_string(str
) : RECLAIM_NONE
;
4487 str
= database_get_data(conf_node
, "auto_reclaim_delay", RECDB_QSTRING
);
4488 nickserv_conf
.auto_reclaim_delay
= str
? ParseInterval(str
) : 0;
4490 child
= database_get_data(conf_node
, KEY_FLAG_LEVELS
, RECDB_OBJECT
);
4491 for (it
=dict_first(child
); it
; it
=iter_next(it
)) {
4492 const char *key
= iter_key(it
), *value
;
4496 if (!strncasecmp(key
, "uc_", 3))
4497 flag
= toupper(key
[3]);
4498 else if (!strncasecmp(key
, "lc_", 3))
4499 flag
= tolower(key
[3]);
4503 if ((pos
= handle_inverse_flags
[flag
])) {
4504 value
= GET_RECORD_QSTRING((struct record_data
*)iter_data(it
));
4505 flag_access_levels
[pos
- 1] = strtoul(value
, NULL
, 0);
4508 if (nickserv_conf
.weak_password_dict
)
4509 dict_delete(nickserv_conf
.weak_password_dict
);
4510 nickserv_conf
.weak_password_dict
= dict_new();
4511 dict_set_free_keys(nickserv_conf
.weak_password_dict
, free
);
4512 dict_insert(nickserv_conf
.weak_password_dict
, strdup("password"), NULL
);
4513 dict_insert(nickserv_conf
.weak_password_dict
, strdup("<password>"), NULL
);
4514 str
= database_get_data(conf_node
, KEY_DICT_FILE
, RECDB_QSTRING
);
4516 nickserv_load_dict(str
);
4517 str
= database_get_data(conf_node
, KEY_NICK
, RECDB_QSTRING
);
4518 if (nickserv
&& str
)
4519 NickChange(nickserv
, str
, 0);
4520 str
= database_get_data(conf_node
, KEY_AUTOGAG_ENABLED
, RECDB_QSTRING
);
4521 nickserv_conf
.autogag_enabled
= str
? strtoul(str
, NULL
, 0) : 1;
4522 str
= database_get_data(conf_node
, KEY_AUTOGAG_DURATION
, RECDB_QSTRING
);
4523 nickserv_conf
.autogag_duration
= str
? ParseInterval(str
) : 1800;
4524 str
= database_get_data(conf_node
, KEY_EMAIL_VISIBLE_LEVEL
, RECDB_QSTRING
);
4525 nickserv_conf
.email_visible_level
= str
? strtoul(str
, NULL
, 0) : 800;
4526 str
= database_get_data(conf_node
, KEY_EMAIL_ENABLED
, RECDB_QSTRING
);
4527 nickserv_conf
.email_enabled
= str
? enabled_string(str
) : 0;
4528 str
= database_get_data(conf_node
, KEY_SYNC_LOG
, RECDB_QSTRING
);
4529 nickserv_conf
.sync_log
= str
? enabled_string(str
) : 0;
4530 str
= database_get_data(conf_node
, KEY_COOKIE_TIMEOUT
, RECDB_QSTRING
);
4531 nickserv_conf
.cookie_timeout
= str
? ParseInterval(str
) : 24*3600;
4532 str
= database_get_data(conf_node
, KEY_EMAIL_REQUIRED
, RECDB_QSTRING
);
4533 nickserv_conf
.email_required
= (nickserv_conf
.email_enabled
&& str
) ? enabled_string(str
) : 0;
4534 str
= database_get_data(conf_node
, KEY_ACCOUNTS_PER_EMAIL
, RECDB_QSTRING
);
4535 nickserv_conf
.handles_per_email
= str
? strtoul(str
, NULL
, 0) : 1;
4536 str
= database_get_data(conf_node
, KEY_EMAIL_SEARCH_LEVEL
, RECDB_QSTRING
);
4537 nickserv_conf
.email_search_level
= str
? strtoul(str
, NULL
, 0) : 600;
4538 str
= database_get_data(conf_node
, KEY_TITLEHOST_SUFFIX
, RECDB_QSTRING
);
4539 nickserv_conf
.titlehost_suffix
= str
? str
: "example.net";
4541 free_string_list(nickserv_conf
.denied_fakehost_words
);
4542 strlist
= database_get_data(conf_node
, KEY_DENIED_FAKEHOST_WORDS
, RECDB_STRING_LIST
);
4544 strlist
= string_list_copy(strlist
);
4546 strlist
= alloc_string_list(4);
4547 string_list_append(strlist
, strdup("sex"));
4548 string_list_append(strlist
, strdup("fuck"));
4550 nickserv_conf
.denied_fakehost_words
= strlist
;
4552 str
= database_get_data(conf_node
, KEY_DEFAULT_STYLE
, RECDB_QSTRING
);
4553 nickserv_conf
.default_style
= str
? str
[0] : HI_DEFAULT_STYLE
;
4555 str
= database_get_data(conf_node
, KEY_AUTO_OPER
, RECDB_QSTRING
);
4556 nickserv_conf
.auto_oper
= str
? str
: "";
4558 str
= database_get_data(conf_node
, KEY_AUTO_ADMIN
, RECDB_QSTRING
);
4559 nickserv_conf
.auto_admin
= str
? str
: "";
4561 str
= conf_get_data("server/network", RECDB_QSTRING
);
4562 nickserv_conf
.network_name
= str
? str
: "some IRC network";
4563 if (!nickserv_conf
.auth_policer_params
) {
4564 nickserv_conf
.auth_policer_params
= policer_params_new();
4565 policer_params_set(nickserv_conf
.auth_policer_params
, "size", "5");
4566 policer_params_set(nickserv_conf
.auth_policer_params
, "drain-rate", "0.05");
4568 child
= database_get_data(conf_node
, KEY_AUTH_POLICER
, RECDB_OBJECT
);
4569 for (it
=dict_first(child
); it
; it
=iter_next(it
))
4570 set_policer_param(iter_key(it
), iter_data(it
), nickserv_conf
.auth_policer_params
);
4572 str
= database_get_data(conf_node
, KEY_LDAP_ENABLE
, RECDB_QSTRING
);
4573 nickserv_conf
.ldap_enable
= str
? strtoul(str
, NULL
, 0) : 0;
4575 if(nickserv_conf
.ldap_enable
> 0) {
4576 /* ldap is enabled but not compiled in - error out */
4577 log_module(MAIN_LOG
, LOG_ERROR
, "ldap is enabled in config, but not compiled in!");
4578 nickserv_conf
.ldap_enable
= 0;
4584 str
= database_get_data(conf_node
, KEY_LDAP_HOST
, RECDB_QSTRING
);
4585 nickserv_conf
.ldap_host
= str
? str
: "";
4587 str
= database_get_data(conf_node
, KEY_LDAP_PORT
, RECDB_QSTRING
);
4588 nickserv_conf
.ldap_port
= str
? strtoul(str
, NULL
, 0) : LDAP_PORT
;
4590 str
= database_get_data(conf_node
, KEY_LDAP_BASE
, RECDB_QSTRING
);
4591 nickserv_conf
.ldap_base
= str
? str
: "";
4593 str
= database_get_data(conf_node
, KEY_LDAP_DN_FMT
, RECDB_QSTRING
);
4594 nickserv_conf
.ldap_dn_fmt
= str
? str
: "";
4596 str
= database_get_data(conf_node
, KEY_LDAP_VERSION
, RECDB_QSTRING
);
4597 nickserv_conf
.ldap_version
= str
? strtoul(str
, NULL
, 0) : 3;
4599 str
= database_get_data(conf_node
, KEY_LDAP_AUTOCREATE
, RECDB_QSTRING
);
4600 nickserv_conf
.ldap_autocreate
= str
? strtoul(str
, NULL
, 0) : 0;
4602 str
= database_get_data(conf_node
, KEY_LDAP_ADMIN_DN
, RECDB_QSTRING
);
4603 nickserv_conf
.ldap_admin_dn
= str
? str
: "";
4605 str
= database_get_data(conf_node
, KEY_LDAP_ADMIN_PASS
, RECDB_QSTRING
);
4606 nickserv_conf
.ldap_admin_pass
= str
? str
: "";
4608 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_ACCOUNT
, RECDB_QSTRING
);
4609 nickserv_conf
.ldap_field_account
= str
? str
: "";
4611 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_PASSWORD
, RECDB_QSTRING
);
4612 nickserv_conf
.ldap_field_password
= str
? str
: "";
4614 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_EMAIL
, RECDB_QSTRING
);
4615 nickserv_conf
.ldap_field_email
= str
? str
: "";
4617 str
= database_get_data(conf_node
, KEY_LDAP_OPER_GROUP_DN
, RECDB_QSTRING
);
4618 nickserv_conf
.ldap_oper_group_dn
= str
? str
: "";
4620 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_GROUP_MEMBER
, RECDB_QSTRING
);
4621 nickserv_conf
.ldap_field_group_member
= str
? str
: "";
4623 free_string_list(nickserv_conf
.ldap_object_classes
);
4624 strlist
= database_get_data(conf_node
, KEY_LDAP_OBJECT_CLASSES
, RECDB_STRING_LIST
);
4626 strlist
= string_list_copy(strlist
);
4628 strlist
= alloc_string_list(4);
4629 string_list_append(strlist
, strdup("top"));
4631 nickserv_conf
.ldap_object_classes
= strlist
;
4638 nickserv_reclaim(struct userNode
*user
, struct nick_info
*ni
, enum reclaim_action action
) {
4640 char newnick
[NICKLEN
+1];
4649 send_message(user
, nickserv
, "NSMSG_RECLAIM_WARN", ni
->nick
, ni
->owner
->handle
);
4651 case RECLAIM_SVSNICK
:
4653 snprintf(newnick
, sizeof(newnick
), "Guest%d", rand()%10000
);
4654 } while (GetUserH(newnick
));
4655 irc_svsnick(nickserv
, user
, newnick
);
4658 msg
= user_find_message(user
, "NSMSG_RECLAIM_KILL");
4659 irc_kill(nickserv
, user
, msg
);
4665 nickserv_reclaim_p(void *data
) {
4666 struct userNode
*user
= data
;
4667 struct nick_info
*ni
= get_nick_info(user
->nick
);
4669 nickserv_reclaim(user
, ni
, nickserv_conf
.auto_reclaim_action
);
4673 check_user_nick(struct userNode
*user
) {
4674 struct nick_info
*ni
;
4675 user
->modes
&= ~FLAGS_REGNICK
;
4676 if (!(ni
= get_nick_info(user
->nick
)))
4678 if (user
->handle_info
== ni
->owner
) {
4679 user
->modes
|= FLAGS_REGNICK
;
4683 if (nickserv_conf
.warn_nick_owned
)
4684 send_message(user
, nickserv
, "NSMSG_RECLAIM_WARN", ni
->nick
, ni
->owner
->handle
);
4685 if (nickserv_conf
.auto_reclaim_action
== RECLAIM_NONE
)
4687 if (nickserv_conf
.auto_reclaim_delay
)
4688 timeq_add(now
+ nickserv_conf
.auto_reclaim_delay
, nickserv_reclaim_p
, user
);
4690 nickserv_reclaim(user
, ni
, nickserv_conf
.auto_reclaim_action
);
4695 handle_new_user(struct userNode
*user
)
4697 return check_user_nick(user
);
4701 handle_account(struct userNode
*user
, const char *stamp
)
4703 struct handle_info
*hi
;
4706 #ifdef WITH_PROTOCOL_P10
4707 time_t timestamp
= 0;
4709 colon
= strchr(stamp
, ':');
4710 if(colon
&& colon
[1])
4713 timestamp
= atoi(colon
+1);
4715 hi
= dict_find(nickserv_handle_dict
, stamp
, NULL
);
4716 if(hi
&& timestamp
&& hi
->registered
!= timestamp
)
4718 log_module(MAIN_LOG
, LOG_WARNING
, "%s using account %s but timestamp does not match %lu is not %lu.", user
->nick
, stamp
, timestamp
, hi
->registered
);
4722 hi
= dict_find(nickserv_id_dict
, stamp
, NULL
);
4723 log_module(MAIN_LOG
, LOG_WARNING
, "Using non-P10 code in accounts, not tested at all!");
4727 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
4730 set_user_handle_info(user
, hi
, 0);
4732 log_module(MAIN_LOG
, LOG_WARNING
, "%s had unknown account stamp %s.", user
->nick
, stamp
);
4737 handle_nick_change(struct userNode
*user
, const char *old_nick
)
4739 struct handle_info
*hi
;
4741 if ((hi
= dict_find(nickserv_allow_auth_dict
, old_nick
, 0))) {
4742 dict_remove(nickserv_allow_auth_dict
, old_nick
);
4743 dict_insert(nickserv_allow_auth_dict
, user
->nick
, hi
);
4745 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
4746 check_user_nick(user
);
4750 nickserv_remove_user(struct userNode
*user
, UNUSED_ARG(struct userNode
*killer
), UNUSED_ARG(const char *why
))
4752 dict_remove(nickserv_allow_auth_dict
, user
->nick
);
4753 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
4754 set_user_handle_info(user
, NULL
, 0);
4757 static struct modcmd
*
4758 nickserv_define_func(const char *name
, modcmd_func_t func
, int min_level
, int must_auth
, int must_be_qualified
)
4760 if (min_level
> 0) {
4762 sprintf(buf
, "%u", min_level
);
4763 if (must_be_qualified
) {
4764 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "level", buf
, "flags", "+qualified,+loghostmask", NULL
);
4766 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "level", buf
, NULL
);
4768 } else if (min_level
== 0) {
4769 if (must_be_qualified
) {
4770 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+helping", NULL
);
4772 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+helping", NULL
);
4775 if (must_be_qualified
) {
4776 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+qualified,+loghostmask", NULL
);
4778 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), NULL
);
4784 nickserv_db_cleanup(void)
4786 unreg_del_user_func(nickserv_remove_user
);
4787 userList_clean(&curr_helpers
);
4788 policer_params_delete(nickserv_conf
.auth_policer_params
);
4789 dict_delete(nickserv_handle_dict
);
4790 dict_delete(nickserv_nick_dict
);
4791 dict_delete(nickserv_opt_dict
);
4792 dict_delete(nickserv_allow_auth_dict
);
4793 dict_delete(nickserv_email_dict
);
4794 dict_delete(nickserv_id_dict
);
4795 dict_delete(nickserv_conf
.weak_password_dict
);
4796 free(auth_func_list
);
4797 free(unreg_func_list
);
4799 free(allowauth_func_list
);
4800 free(handle_merge_func_list
);
4801 free(failpw_func_list
);
4802 if (nickserv_conf
.valid_handle_regex_set
)
4803 regfree(&nickserv_conf
.valid_handle_regex
);
4804 if (nickserv_conf
.valid_nick_regex_set
)
4805 regfree(&nickserv_conf
.valid_nick_regex
);
4809 init_nickserv(const char *nick
)
4811 struct chanNode
*chan
;
4813 NS_LOG
= log_register_type("NickServ", "file:nickserv.log");
4814 reg_new_user_func(handle_new_user
);
4815 reg_nick_change_func(handle_nick_change
);
4816 reg_del_user_func(nickserv_remove_user
);
4817 reg_account_func(handle_account
);
4819 /* set up handle_inverse_flags */
4820 memset(handle_inverse_flags
, 0, sizeof(handle_inverse_flags
));
4821 for (i
=0; handle_flags
[i
]; i
++) {
4822 handle_inverse_flags
[(unsigned char)handle_flags
[i
]] = i
+ 1;
4823 flag_access_levels
[i
] = 0;
4826 conf_register_reload(nickserv_conf_read
);
4827 nickserv_opt_dict
= dict_new();
4828 nickserv_email_dict
= dict_new();
4830 dict_set_free_keys(nickserv_email_dict
, free
);
4831 dict_set_free_data(nickserv_email_dict
, nickserv_free_email_addr
);
4833 nickserv_module
= module_register("NickServ", NS_LOG
, "nickserv.help", NULL
);
4834 /* Removed qualified_host as default requirement for AUTH, REGISTER, PASS, etc. nets
4835 * can enable it per command using modcmd. (its a shitty default IMO, and now in 1.3
4836 * a big pain to disable since its nolonger in the config file. ) -Rubin
4838 modcmd_register(nickserv_module
, "AUTH", cmd_auth
, 2, MODCMD_KEEP_BOUND
, "flags", "+loghostmask", NULL
);
4839 nickserv_define_func("ALLOWAUTH", cmd_allowauth
, 0, 1, 0);
4840 nickserv_define_func("REGISTER", cmd_register
, -1, 0, 0);
4841 nickserv_define_func("OREGISTER", cmd_oregister
, 0, 1, 0);
4842 nickserv_define_func("UNREGISTER", cmd_unregister
, -1, 1, 0);
4843 nickserv_define_func("OUNREGISTER", cmd_ounregister
, 0, 1, 0);
4844 nickserv_define_func("ADDMASK", cmd_addmask
, -1, 1, 0);
4845 nickserv_define_func("OADDMASK", cmd_oaddmask
, 0, 1, 0);
4846 nickserv_define_func("DELMASK", cmd_delmask
, -1, 1, 0);
4847 nickserv_define_func("ODELMASK", cmd_odelmask
, 0, 1, 0);
4848 nickserv_define_func("PASS", cmd_pass
, -1, 1, 0);
4849 nickserv_define_func("SET", cmd_set
, -1, 1, 0);
4850 nickserv_define_func("OSET", cmd_oset
, 0, 1, 0);
4851 nickserv_define_func("ACCOUNTINFO", cmd_handleinfo
, -1, 0, 0);
4852 nickserv_define_func("USERINFO", cmd_userinfo
, -1, 1, 0);
4853 nickserv_define_func("RENAME", cmd_rename_handle
, -1, 1, 0);
4854 nickserv_define_func("VACATION", cmd_vacation
, -1, 1, 0);
4855 nickserv_define_func("MERGE", cmd_merge
, 0, 1, 0);
4856 if (!nickserv_conf
.disable_nicks
) {
4857 /* nick management commands */
4858 nickserv_define_func("REGNICK", cmd_regnick
, -1, 1, 0);
4859 nickserv_define_func("OREGNICK", cmd_oregnick
, 0, 1, 0);
4860 nickserv_define_func("UNREGNICK", cmd_unregnick
, -1, 1, 0);
4861 nickserv_define_func("OUNREGNICK", cmd_ounregnick
, 0, 1, 0);
4862 nickserv_define_func("NICKINFO", cmd_nickinfo
, -1, 1, 0);
4863 nickserv_define_func("RECLAIM", cmd_reclaim
, -1, 1, 0);
4865 if (nickserv_conf
.email_enabled
) {
4866 nickserv_define_func("AUTHCOOKIE", cmd_authcookie
, -1, 0, 0);
4867 nickserv_define_func("RESETPASS", cmd_resetpass
, -1, 0, 0);
4868 nickserv_define_func("COOKIE", cmd_cookie
, -1, 0, 0);
4869 nickserv_define_func("DELCOOKIE", cmd_delcookie
, -1, 1, 0);
4870 nickserv_define_func("ODELCOOKIE", cmd_odelcookie
, 0, 1, 0);
4871 dict_insert(nickserv_opt_dict
, "EMAIL", opt_email
);
4873 nickserv_define_func("GHOST", cmd_ghost
, -1, 1, 0);
4874 /* ignore commands */
4875 nickserv_define_func("ADDIGNORE", cmd_addignore
, -1, 1, 0);
4876 nickserv_define_func("OADDIGNORE", cmd_oaddignore
, 0, 1, 0);
4877 nickserv_define_func("DELIGNORE", cmd_delignore
, -1, 1, 0);
4878 nickserv_define_func("ODELIGNORE", cmd_odelignore
, 0, 1, 0);
4879 /* miscellaneous commands */
4880 nickserv_define_func("STATUS", cmd_status
, -1, 0, 0);
4881 nickserv_define_func("SEARCH", cmd_search
, 100, 1, 0);
4882 nickserv_define_func("SEARCH UNREGISTER", NULL
, 800, 1, 0);
4883 nickserv_define_func("MERGEDB", cmd_mergedb
, 999, 1, 0);
4884 nickserv_define_func("CHECKPASS", cmd_checkpass
, 601, 1, 0);
4886 dict_insert(nickserv_opt_dict
, "INFO", opt_info
);
4887 dict_insert(nickserv_opt_dict
, "WIDTH", opt_width
);
4888 dict_insert(nickserv_opt_dict
, "TABLEWIDTH", opt_tablewidth
);
4889 dict_insert(nickserv_opt_dict
, "COLOR", opt_color
);
4890 dict_insert(nickserv_opt_dict
, "PRIVMSG", opt_privmsg
);
4891 dict_insert(nickserv_opt_dict
, "AUTOHIDE", opt_autohide
);
4892 dict_insert(nickserv_opt_dict
, "STYLE", opt_style
);
4893 dict_insert(nickserv_opt_dict
, "PASS", opt_password
);
4894 dict_insert(nickserv_opt_dict
, "PASSWORD", opt_password
);
4895 dict_insert(nickserv_opt_dict
, "FLAGS", opt_flags
);
4896 dict_insert(nickserv_opt_dict
, "ACCESS", opt_level
);
4897 dict_insert(nickserv_opt_dict
, "LEVEL", opt_level
);
4898 dict_insert(nickserv_opt_dict
, "EPITHET", opt_epithet
);
4899 dict_insert(nickserv_opt_dict
, "NOTE", opt_note
);
4900 if (nickserv_conf
.titlehost_suffix
) {
4901 dict_insert(nickserv_opt_dict
, "TITLE", opt_title
);
4902 dict_insert(nickserv_opt_dict
, "FAKEHOST", opt_fakehost
);
4904 dict_insert(nickserv_opt_dict
, "ANNOUNCEMENTS", opt_announcements
);
4905 dict_insert(nickserv_opt_dict
, "MAXLOGINS", opt_maxlogins
);
4906 dict_insert(nickserv_opt_dict
, "ADVANCED", opt_advanced
);
4907 dict_insert(nickserv_opt_dict
, "LANGUAGE", opt_language
);
4909 nickserv_handle_dict
= dict_new();
4910 dict_set_free_keys(nickserv_handle_dict
, free
);
4911 dict_set_free_data(nickserv_handle_dict
, free_handle_info
);
4913 nickserv_id_dict
= dict_new();
4914 dict_set_free_keys(nickserv_id_dict
, free
);
4916 nickserv_nick_dict
= dict_new();
4917 dict_set_free_data(nickserv_nick_dict
, free
);
4919 nickserv_allow_auth_dict
= dict_new();
4921 userList_init(&curr_helpers
);
4924 const char *modes
= conf_get_data("services/nickserv/modes", RECDB_QSTRING
);
4925 nickserv
= AddService(nick
, modes
? modes
: NULL
, "Nick Services", NULL
);
4926 nickserv_service
= service_register(nickserv
);
4928 saxdb_register("NickServ", nickserv_saxdb_read
, nickserv_saxdb_write
);
4929 reg_exit_func(nickserv_db_cleanup
);
4930 if(nickserv_conf
.handle_expire_frequency
)
4931 timeq_add(now
+ nickserv_conf
.handle_expire_frequency
, expire_handles
, NULL
);
4933 if(autojoin_channels
&& nickserv
) {
4934 for (i
= 0; i
< autojoin_channels
->used
; i
++) {
4935 chan
= AddChannel(autojoin_channels
->list
[i
], now
, "+nt", NULL
, NULL
);
4936 AddChannelUser(nickserv
, chan
)->modes
|= MODE_CHANOP
;
4940 ldap_do_init(nickserv_conf
);
4943 message_register_table(msgtab
);