1 /* nickserv.c - Nick/authentication service
2 * Copyright 2000-2004 srvx Development Team
4 * This file is part of x3.
6 * x3 is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with srvx; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 #include "opserv.h" /* for gag_create(), opserv_bad_channel() */
33 #include <tre/regex.h>
39 #define NICKSERV_CONF_NAME "services/nickserv"
41 #define KEY_DISABLE_NICKS "disable_nicks"
42 #define KEY_DEFAULT_HOSTMASK "default_hostmask"
43 #define KEY_NICKS_PER_HANDLE "nicks_per_handle"
44 #define KEY_NICKS_PER_ACCOUNT "nicks_per_account"
45 #define KEY_PASSWORD_MIN_LENGTH "password_min_length"
46 #define KEY_PASSWORD_MIN_DIGITS "password_min_digits"
47 #define KEY_PASSWORD_MIN_UPPER "password_min_upper"
48 #define KEY_PASSWORD_MIN_LOWER "password_min_lower"
49 #define KEY_VALID_HANDLE_REGEX "valid_handle_regex"
50 #define KEY_VALID_ACCOUNT_REGEX "valid_account_regex"
51 #define KEY_VALID_NICK_REGEX "valid_nick_regex"
52 #define KEY_VALID_FAKEHOST_REGEX "valid_fakehost_regex"
53 #define KEY_DB_BACKUP_FREQ "db_backup_freq"
54 #define KEY_MODOPER_LEVEL "modoper_level"
55 #define KEY_SET_EPITHET_LEVEL "set_epithet_level"
56 #define KEY_SET_TITLE_LEVEL "set_title_level"
57 #define KEY_SET_FAKEHOST_LEVEL "set_fakehost_level"
58 #define KEY_DENIED_FAKEHOST_WORDS "denied_fakehost_words"
59 #define KEY_TITLEHOST_SUFFIX "titlehost_suffix"
60 #define KEY_AUTO_OPER "auto_oper"
61 #define KEY_AUTO_ADMIN "auto_admin"
62 #define KEY_AUTO_OPER_PRIVS "auto_oper_privs"
63 #define KEY_AUTO_ADMIN_PRIVS "auto_admin_privs"
64 #define KEY_FLAG_LEVELS "flag_levels"
65 #define KEY_HANDLE_EXPIRE_FREQ "handle_expire_freq"
66 #define KEY_ACCOUNT_EXPIRE_FREQ "account_expire_freq"
67 #define KEY_HANDLE_EXPIRE_DELAY "handle_expire_delay"
68 #define KEY_NICK_EXPIRE_FREQ "nick_expire_freq"
69 #define KEY_NICK_EXPIRE_DELAY "nick_expire_delay"
70 #define KEY_ACCOUNT_EXPIRE_DELAY "account_expire_delay"
71 #define KEY_NOCHAN_HANDLE_EXPIRE_DELAY "nochan_handle_expire_delay"
72 #define KEY_NOCHAN_ACCOUNT_EXPIRE_DELAY "nochan_account_expire_delay"
73 #define KEY_DICT_FILE "dict_file"
74 #define KEY_NICK "nick"
75 #define KEY_LANGUAGE "language"
76 #define KEY_AUTOGAG_ENABLED "autogag_enabled"
77 #define KEY_AUTOGAG_DURATION "autogag_duration"
78 #define KEY_AUTH_POLICER "auth_policer"
79 #define KEY_EMAIL_VISIBLE_LEVEL "email_visible_level"
80 #define KEY_EMAIL_ENABLED "email_enabled"
81 #define KEY_EMAIL_REQUIRED "email_required"
82 #define KEY_SYNC_LOG "sync_log"
83 #define KEY_COOKIE_TIMEOUT "cookie_timeout"
84 #define KEY_ACCOUNTS_PER_EMAIL "accounts_per_email"
85 #define KEY_EMAIL_SEARCH_LEVEL "email_search_level"
86 #define KEY_DEFAULT_STYLE "default_style"
87 #define KEY_OUNREGISTER_INACTIVE "ounregister_inactive"
88 #define KEY_OUNREGISTER_FLAGS "ounregister_flags"
91 #define KEY_PASSWD "passwd"
92 #define KEY_NICKS "nicks"
93 #define KEY_NICKS_EX "nicks_ex"
94 #define KEY_MASKS "masks"
95 #define KEY_SSLFPS "sslfps"
96 #define KEY_IGNORES "ignores"
97 #define KEY_OPSERV_LEVEL "opserv_level"
98 #define KEY_FLAGS "flags"
99 #define KEY_REGISTER_ON "register"
100 #define KEY_LAST_SEEN "lastseen"
101 #define KEY_INFO "info"
102 #define KEY_USERLIST_STYLE "user_style"
103 #define KEY_SCREEN_WIDTH "screen_width"
104 #define KEY_LAST_AUTHED_HOST "last_authed_host"
105 #define KEY_LAST_QUIT_HOST "last_quit_host"
106 #define KEY_EMAIL_ADDR "email_addr"
107 #define KEY_COOKIE "cookie"
108 #define KEY_COOKIE_DATA "data"
109 #define KEY_COOKIE_TYPE "type"
110 #define KEY_COOKIE_EXPIRES "expires"
111 #define KEY_ACTIVATION "activation"
112 #define KEY_PASSWORD_CHANGE "password change"
113 #define KEY_EMAIL_CHANGE "email change"
114 #define KEY_ALLOWAUTH "allowauth"
115 #define KEY_EPITHET "epithet"
116 #define KEY_TABLE_WIDTH "table_width"
117 #define KEY_ANNOUNCEMENTS "announcements"
118 #define KEY_MAXLOGINS "maxlogins"
119 #define KEY_FAKEHOST "fakehost"
120 #define KEY_NOTE_NOTE "note"
121 #define KEY_NOTE_SETTER "setter"
122 #define KEY_NOTE_DATE "date"
123 #define KEY_KARMA "karma"
124 #define KEY_FORCE_HANDLES_LOWERCASE "force_handles_lowercase"
126 #define KEY_LDAP_ENABLE "ldap_enable"
129 #define KEY_LDAP_URI "ldap_uri"
130 #define KEY_LDAP_BASE "ldap_base"
131 #define KEY_LDAP_DN_FMT "ldap_dn_fmt"
132 #define KEY_LDAP_VERSION "ldap_version"
133 #define KEY_LDAP_AUTOCREATE "ldap_autocreate"
134 #define KEY_LDAP_ADMIN_DN "ldap_admin_dn"
135 #define KEY_LDAP_ADMIN_PASS "ldap_admin_pass"
136 #define KEY_LDAP_FIELD_ACCOUNT "ldap_field_account"
137 #define KEY_LDAP_FIELD_PASSWORD "ldap_field_password"
138 #define KEY_LDAP_FIELD_EMAIL "ldap_field_email"
139 #define KEY_LDAP_FIELD_OSLEVEL "ldap_field_oslevel"
140 #define KEY_LDAP_OBJECT_CLASSES "ldap_object_classes"
141 #define KEY_LDAP_OPER_GROUP_DN "ldap_oper_group_dn"
142 #define KEY_LDAP_OPER_GROUP_LEVEL "ldap_oper_group_level"
143 #define KEY_LDAP_FIELD_GROUP_MEMBER "ldap_field_group_member"
144 #define KEY_LDAP_TIMEOUT "ldap_timeout"
147 #define NICKSERV_VALID_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
149 #define NICKSERV_FUNC(NAME) MODCMD_FUNC(NAME)
150 #define OPTION_FUNC(NAME) int NAME(UNUSED_ARG(struct svccmd *cmd), struct userNode *user, struct handle_info *hi, UNUSED_ARG(unsigned int override), int noreply, unsigned int argc, char *argv[])
151 typedef OPTION_FUNC(option_func_t
);
153 DEFINE_LIST(handle_info_list
, struct handle_info
*)
155 #define NICKSERV_MIN_PARMS(N) do { \
157 reply("MSG_MISSING_PARAMS", argv[0]); \
158 svccmd_send_help_brief(user, nickserv, cmd); \
162 struct userNode
*nickserv
;
163 struct userList curr_helpers
;
164 const char *handle_flags
= HANDLE_FLAGS
;
166 extern struct string_list
*autojoin_channels
;
167 static struct module *nickserv_module
;
168 static struct service
*nickserv_service
;
169 static struct log_type
*NS_LOG
;
170 dict_t nickserv_handle_dict
; /* contains struct handle_info* */
171 static dict_t nickserv_id_dict
; /* contains struct handle_info* */
172 static dict_t nickserv_nick_dict
; /* contains struct nick_info* */
173 static dict_t nickserv_opt_dict
; /* contains option_func_t* */
174 static dict_t nickserv_allow_auth_dict
; /* contains struct handle_info* */
175 static dict_t nickserv_email_dict
; /* contains struct handle_info_list*, indexed by email addr */
176 static char handle_inverse_flags
[256];
177 static unsigned int flag_access_levels
[32];
178 static const struct message_entry msgtab
[] = {
179 { "NSMSG_NO_ANGLEBRACKETS", "The < and > in help indicate that that word is a required parameter, but DO NOT actually type them in messages to me." },
180 { "NSMSG_HANDLE_EXISTS", "Account $b%s$b is already registered." },
181 { "NSMSG_HANDLE_TOLONG", "The account name %s is too long. Account names must be %lu characters or less."},
182 { "NSMSG_PASSWORD_SHORT", "Your password must be at least %lu characters long." },
183 { "NSMSG_PASSWORD_ACCOUNT", "Your password may not be the same as your account name." },
184 { "NSMSG_PASSWORD_DICTIONARY", "Your password is too simple. You must choose a password that is not just a word or name." },
185 { "NSMSG_PASSWORD_READABLE", "Your password must have at least %lu digit(s), %lu capital letter(s), and %lu lower-case letter(s)." },
186 { "NSMSG_LDAP_FAIL", "There was a problem in contacting the account server (ldap): %s. Please try again later." },
187 { "NSMSG_LDAP_FAIL_ADD", "There was a problem in adding account %s to ldap: %s." },
188 { "NSMSG_LDAP_FAIL_SEND_EMAIL", "There was a problem in storing your email address in the account server (ldap): %s. Please try again later." },
189 { "NSMSG_LDAP_FAIL_GET_EMAIL", "There was a problem in retrieving your email address from the account server (ldap): %s. Please try again later." },
190 { "NSMSG_PARTIAL_REGISTER", "Account has been registered to you; nick was already registered to someone else." },
191 { "NSMSG_OREGISTER_VICTIM", "%s has registered a new account for you (named %s)." },
192 { "NSMSG_OREGISTER_H_SUCCESS", "Account has been registered." },
193 { "NSMSG_REGISTER_H_SUCCESS", "Account has been registered to you." },
194 { "NSMSG_REGISTER_HN_SUCCESS", "Account and nick have been registered to you." },
195 { "NSMSG_REQUIRE_OPER", "You must be an $bIRC Operator$b to register the first account." },
196 { "NSMSG_ROOT_HANDLE", "Account %s has been granted $broot-level privileges$b." },
197 { "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." },
198 { "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." },
199 { "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." },
200 { "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." },
201 { "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." },
202 { "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." },
203 { "NSMSG_EMAIL_UNACTIVATED", "That email address already has an unused cookie outstanding. Please use the cookie or wait for it to expire." },
204 { "NSMSG_NO_COOKIE", "Your account does not have any cookie issued right now." },
205 { "NSMSG_NO_COOKIE_FOREIGN", "The account $b%s$b does not have any cookie issued right now." },
206 { "NSMSG_CANNOT_COOKIE", "You cannot use that kind of cookie when you are logged in." },
207 { "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." },
208 { "NSMSG_HANDLE_ACTIVATED", "Your account is now activated (with the password you entered when you registered). You are now authenticated to your account." },
209 { "NSMSG_PASSWORD_CHANGED", "You have successfully changed your password to what you requested with the $bresetpass$b command." },
210 { "NSMSG_EMAIL_PROHIBITED", "%s may not be used as an email address: %s" },
211 { "NSMSG_EMAIL_OVERUSED", "That email address already has an account. Use RESETPASS if you forgot your password." },
212 { "NSMSG_EMAIL_SAME", "That is the email address already there; no need to change it." },
213 { "NSMSG_EMAIL_CHANGED", "You have successfully changed your email address." },
214 { "NSMSG_BAD_COOKIE_TYPE", "Your account had bad cookie type %d; sorry. I am confused. Please report this bug." },
215 { "NSMSG_MUST_TIME_OUT", "You must wait for cookies of that type to time out." },
216 { "NSMSG_ATE_COOKIE", "I ate the cookie for your account. You may now have another." },
217 { "NSMSG_ATE_FOREIGN_COOKIE", "I ate the cookie for account $b%s$b. It may now have another." },
218 { "NSMSG_USE_RENAME", "You are already authenticated to account $b%s$b -- contact the support staff to rename your account." },
219 { "NSMSG_ALREADY_REGISTERING", "You have already used $bREGISTER$b once this session; you may not use it again." },
220 { "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 *@*)." },
221 { "NSMSG_NICK_NOT_REGISTERED", "Nick $b%s$b has not been registered to any account." },
222 { "NSMSG_HANDLE_NOT_FOUND", "Could not find your account -- did you register yet?" },
223 { "NSMSG_ALREADY_AUTHED", "You are already authed to account $b%s$b; you must reconnect to auth to a different account." },
224 { "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 $N authcookie %1$s)" },
225 { "NSMSG_HOSTMASK_INVALID", "Your hostmask is not valid for account $b%s$b." },
226 { "NSMSG_USER_IS_SERVICE", "$b%s$b is a network service; you can only use that command on real users." },
227 { "NSMSG_USER_PREV_AUTH", "$b%s$b is already authenticated." },
228 { "NSMSG_USER_PREV_STAMP", "$b%s$b has authenticated to an account once and cannot authenticate again." },
229 { "NSMSG_BAD_MAX_LOGINS", "MaxLogins must be at most %d." },
230 { "NSMSG_BAD_ADVANCED", "Advanced must be either 1 to enable it or 0 to disable it." },
231 { "NSMSG_LANGUAGE_NOT_FOUND", "Language $b%s$b is not supported; $b%s$b was the closest available match." },
232 { "NSMSG_MAX_LOGINS", "Your account already has its limit of %d user(s) logged in." },
233 { "NSMSG_STAMPED_REGISTER", "You have already authenticated to an account once this session; you may not register a new account." },
234 { "NSMSG_STAMPED_AUTH", "You have already authenticated to an account once this session; you may not authenticate to another." },
235 { "NSMSG_STAMPED_RESETPASS", "You have already authenticated to an account once this session; you may not reset your password to authenticate again." },
236 { "NSMSG_STAMPED_AUTHCOOKIE", "You have already authenticated to an account once this session; you may not use a cookie to authenticate to another account." },
237 { "NSMSG_TITLE_INVALID", "Titles may contain only a-z, A-Z, 0-9, and '-'. Please choose another." },
238 { "NSMSG_TITLE_TRUNCATED", "That title combined with the user's account name would result in a truncated host; please choose a shorter title." },
239 { "NSMSG_FAKEHOST_INVALID", "Fake hosts must be shorter than %d characters and cannot start with a dot." },
240 { "NSMSG_HANDLEINFO_ON", "$bAccount Information for %s$b" },
241 { "NSMSG_HANDLEINFO_END", "----------End of Account Info-----------" },
242 { "NSMSG_HANDLEINFO_ID", "Account ID: %lu" },
243 { "NSMSG_HANDLEINFO_REGGED", "Registered on: %s" },
244 { "NSMSG_HANDLEINFO_LASTSEEN", "Last seen: %s" },
245 { "NSMSG_HANDLEINFO_LASTSEEN_NOW", "Last seen: Right now!" },
246 { "NSMSG_HANDLEINFO_KARMA", "Karma: %d" },
247 { "NSMSG_HANDLEINFO_VACATION", "On vacation." },
248 { "NSMSG_HANDLEINFO_EMAIL_ADDR", "Email address: %s" },
249 { "NSMSG_HANDLEINFO_COOKIE_ACTIVATION", "Cookie: There is currently an activation cookie issued for this account" },
250 { "NSMSG_HANDLEINFO_COOKIE_PASSWORD", "Cookie: There is currently a password change cookie issued for this account" },
251 { "NSMSG_HANDLEINFO_COOKIE_EMAIL", "Cookie: There is currently an email change cookie issued for this account" },
252 { "NSMSG_HANDLEINFO_COOKIE_ALLOWAUTH", "Cookie: There is currently an allowauth cookie issued for this account" },
253 { "NSMSG_HANDLEINFO_COOKIE_UNKNOWN", "Cookie: There is currently an unknown cookie issued for this account" },
254 { "NSMSG_HANDLEINFO_COOKIE_EMAIL_DATA", "Cookie: New email address: %s" },
255 { "NSMSG_HANDLEINFO_INFOLINE", "Infoline: %s" },
256 { "NSMSG_HANDLEINFO_FLAGS", "Flags: %s" },
257 { "NSMSG_HANDLEINFO_EPITHET", "Epithet: %s" },
258 { "NSMSG_HANDLEINFO_NOTE", "Note (by %s on %s): %s " },
259 { "NSMSG_HANDLEINFO_FAKEHOST", "Fake host: %s" },
260 { "NSMSG_INVALID_KARMA", "$b%s$b is not a valid karma modifier." },
261 { "NSMSG_SET_KARMA", "$bKARMA: $b%d$b" },
262 { "NSMSG_HANDLEINFO_LAST_HOST", "Last quit hostmask: %s" },
263 { "NSMSG_HANDLEINFO_LAST_HOST_UNKNOWN", "Last quit hostmask: Unknown" },
264 { "NSMSG_HANDLEINFO_NICKS", "Nickname(s): %s" },
265 { "NSMSG_HANDLEINFO_MASKS", "Hostmask(s): %s" },
266 { "NSMSG_HANDLEINFO_SSLFPS", "SSL Fingerprints(s): %s" },
267 { "NSMSG_HANDLEINFO_IGNORES", "Ignore(s): %s" },
268 { "NSMSG_HANDLEINFO_CHANNELS", "Channel(s): %s" },
269 { "NSMSG_HANDLEINFO_CURRENT", "Current nickname(s): %s" },
270 { "NSMSG_HANDLEINFO_DNR", "Do-not-register (by %s): %s" },
271 { "NSMSG_USERINFO_AUTHED_AS", "$b%s$b is authenticated to account $b%s$b." },
272 { "NSMSG_USERINFO_NOT_AUTHED", "$b%s$b is not authenticated to any account." },
273 { "NSMSG_NICKINFO_ON", "$bNick Information for %s$b" },
274 { "NSMSG_NICKINFO_END", "----------End of Nick Info-----------" },
275 { "NSMSG_NICKINFO_REGGED", "Registered on: %s" },
276 { "NSMSG_NICKINFO_LASTSEEN", "Last seen: %s" },
277 { "NSMSG_NICKINFO_LASTSEEN_NOW", "Last seen: Right now!" },
278 { "NSMSG_NICKINFO_OWNER", "Account: %s." },
279 { "NSMSG_PASSWORD_INVALID", "Incorrect password; please try again." },
280 { "NSMSG_PLEASE_SET_EMAIL", "We now require email addresses for users. Please use the $bset email$b command to set your email address!" },
281 { "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)." },
282 { "NSMSG_HANDLE_SUSPENDED", "Your $b$N$b account has been suspended; you may not use it." },
283 { "NSMSG_AUTH_SUCCESS", "I recognize you." },
284 { "NSMSG_ALLOWAUTH_STAFF", "$b%s$b is a helper or oper; please use $bstaff$b after the account name to allowauth." },
285 { "NSMSG_AUTH_ALLOWED", "User $b%s$b may now authenticate to account $b%s$b." },
286 { "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." },
287 { "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." },
288 { "NSMSG_AUTH_NORMAL_ONLY", "User $b%s$b may now only authenticate to accounts with matching hostmasks." },
289 { "NSMSG_AUTH_UNSPECIAL", "User $b%s$b did not have any special auth allowance." },
290 { "NSMSG_MUST_AUTH", "You must be authenticated first." },
291 { "NSMSG_TOO_MANY_NICKS", "You have already registered the maximum permitted number of nicks." },
292 { "NSMSG_NICK_EXISTS", "Nick $b%s$b already registered." },
293 { "NSMSG_REGNICK_SUCCESS", "Nick $b%s$b has been registered to you." },
294 { "NSMSG_OREGNICK_SUCCESS", "Nick $b%s$b has been registered to account $b%s$b." },
295 { "NSMSG_PASS_SUCCESS", "Password changed." },
296 { "NSMSG_MASK_INVALID", "$b%s$b is an invalid hostmask." },
297 { "NSMSG_ADDMASK_ALREADY", "$b%s$b is already a hostmask in your account." },
298 { "NSMSG_ADDMASK_SUCCESS", "Hostmask %s added." },
299 { "NSMSG_ADDIGNORE_ALREADY", "$b%s$b is already an ignored hostmask in your account." },
300 { "NSMSG_ADDIGNORE_SUCCESS", "Hostmask %s added." },
301 { "NSMSG_ADDSSLFP_ALREADY", "$b%s$b is already an SSL fingerprint in your account." },
302 { "NSMSG_ADDSSLFP_SUCCESS", "SSL fingerprint %s added." },
303 { "NSMSG_DELMASK_NOTLAST", "You may not delete your last hostmask." },
304 { "NSMSG_DELMASK_SUCCESS", "Hostmask %s deleted." },
305 { "NSMSG_DELMASK_NOT_FOUND", "Unable to find mask to be deleted." },
306 { "NSMSG_DELSSLFP_SUCCESS", "SSL fingerprint %s deleted." },
307 { "NSMSG_DELSSLFP_NOT_FOUND", "Unable to find SSL fingerprint to be deleted." },
308 { "NSMSG_OPSERV_LEVEL_BAD", "You may not promote another oper above your level." },
309 { "NSMSG_USE_CMD_PASS", "Please use the PASS command to change your password." },
310 { "NSMSG_UNKNOWN_NICK", "I know nothing about nick $b%s$b." },
311 { "NSMSG_NOT_YOUR_NICK", "The nick $b%s$b is not registered to you." },
312 { "NSMSG_NICK_USER_YOU", "I will not let you kill yourself." },
313 { "NSMSG_UNREGNICK_SUCCESS", "Nick $b%s$b has been unregistered." },
314 { "NSMSG_UNREGISTER_SUCCESS", "Account $b%s$b has been unregistered." },
315 { "NSMSG_UNREGISTER_NICKS_SUCCESS", "Account $b%s$b and all its nicks have been unregistered." },
316 { "NSMSG_UNREGISTER_MUST_FORCE", "Account $b%s$b is not inactive or has special flags set; use FORCE to unregister it." },
317 { "NSMSG_UNREGISTER_CANNOT_FORCE", "Account $b%s$b is not inactive or has special flags set; have an IRCOp use FORCE to unregister it." },
318 { "NSMSG_UNREGISTER_NODELETE", "Account $b%s$b is protected from unregistration." },
319 { "NSMSG_HANDLE_STATS", "There are %d nicks registered to your account." },
320 { "NSMSG_HANDLE_NONE", "You are not authenticated against any account." },
321 { "NSMSG_GLOBAL_STATS", "There are %d accounts and %d nicks registered globally." },
322 { "NSMSG_GLOBAL_STATS_NONICK", "There are %d accounts registered." },
323 { "NSMSG_CANNOT_GHOST_SELF", "You may not ghost-kill yourself." },
324 { "NSMSG_CANNOT_GHOST_USER", "$b%s$b is not authed to your account; you may not ghost-kill them." },
325 { "NSMSG_GHOST_KILLED", "$b%s$b has been killed as a ghost." },
326 { "NSMSG_ON_VACATION", "You are now on vacation. Your account will be preserved until you authenticate again." },
327 { "NSMSG_NO_ACCESS", "Access denied." },
328 { "NSMSG_INVALID_FLAG", "$b%c$b is not a valid $N account flag." },
329 { "NSMSG_SET_FLAG", "Applied flags $b%s$b to %s's $N account." },
330 { "NSMSG_FLAG_PRIVILEGED", "You have insufficient access to set flag %c." },
331 { "NSMSG_DB_UNREADABLE", "Unable to read database file %s; check the log for more information." },
332 { "NSMSG_DB_MERGED", "$N merged DB from %s (in "FMT_TIME_T
".%03lu seconds)." },
333 { "NSMSG_HANDLE_CHANGED", "$b%s$b's account name has been changed to $b%s$b." },
334 { "NSMSG_BAD_HANDLE", "Account $b%s$b is not allowed because it is reserved, is too long, or contains invalid characters." },
335 { "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." },
336 { "NSMSG_BAD_EMAIL_ADDR", "Please use a well-formed email address." },
337 { "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." },
338 { "NSMSG_ACCOUNT_SEARCH_RESULTS", "The following accounts were found:" },
339 { "NSMSG_SEARCH_MATCH", "Match: %s" },
340 { "NSMSG_INVALID_ACTION", "%s is an invalid search action." },
341 { "NSMSG_CANNOT_MERGE_SELF", "You cannot merge account $b%s$b with itself." },
342 { "NSMSG_HANDLES_MERGED", "Merged account $b%s$b into $b%s$b." },
343 { "NSMSG_RECLAIM_WARN", "%s is a registered nick - you must auth to account %s or change your nick." },
344 { "NSMSG_RECLAIM_HOWTO", "To auth to account %s you must use /msg %s@%s AUTH %s <password>" },
345 { "NSMSG_RECLAIM_KILL", "Unauthenticated user of nick." },
346 { "NSMSG_RECLAIMED_NONE", "You cannot manually reclaim a nick." },
347 { "NSMSG_RECLAIMED_WARN", "Sent a request for %s to change their nick." },
348 { "NSMSG_RECLAIMED_SVSNICK", "Forcibly changed %s's nick." },
349 { "NSMSG_RECLAIMED_KILL", "Disconnected %s from the network." },
350 { "NSMSG_CLONE_AUTH", "Warning: %s (%s@%s) authed to your account." },
351 { "NSMSG_SETTING_LIST", "$b$N account settings$b" },
352 { "NSMSG_SETTING_LIST_HEADER", "----------------------------------------" },
353 { "NSMSG_SETTING_LIST_END", "-------------End Of Settings------------" },
354 { "NSMSG_INVALID_OPTION", "$b%s$b is an invalid account setting." },
355 { "NSMSG_INVALID_ANNOUNCE", "$b%s$b is an invalid announcements value." },
356 { "NSMSG_SET_INFO", "$bINFO: $b%s" },
357 { "NSMSG_SET_WIDTH", "$bWIDTH: $b%d" },
358 { "NSMSG_SET_TABLEWIDTH", "$bTABLEWIDTH: $b%d" },
359 { "NSMSG_SET_COLOR", "$bCOLOR: $b%s" },
360 { "NSMSG_SET_PRIVMSG", "$bPRIVMSG: $b%s" },
361 { "NSMSG_SET_STYLE", "$bSTYLE: $b%s" },
362 { "NSMSG_SET_ANNOUNCEMENTS", "$bANNOUNCEMENTS: $b%s" },
363 { "NSMSG_SET_AUTOHIDE", "$bAUTOHIDE: $b%s" },
364 { "NSMSG_SET_PASSWORD", "$bPASSWORD: $b%s" },
365 { "NSMSG_SET_FLAGS", "$bFLAGS: $b%s" },
366 { "NSMSG_SET_EMAIL", "$bEMAIL: $b%s" },
367 { "NSMSG_SET_MAXLOGINS", "$bMAXLOGINS: $b%d" },
368 { "NSMSG_SET_ADVANCED", "$bADVANCED: $b%s" },
369 { "NSMSG_SET_LANGUAGE", "$bLANGUAGE: $b%s" },
370 { "NSMSG_SET_LEVEL", "$bLEVEL: $b%d" },
371 { "NSMSG_SET_EPITHET", "$bEPITHET: $b%s" },
372 { "NSMSG_SET_NOTE", "$bNOTE: $b%s"},
373 { "NSMSG_SET_TITLE", "$bTITLE: $b%s" },
374 { "NSMSG_SET_FAKEHOST", "$bFAKEHOST: $b%s" },
376 { "NSMSG_AUTO_OPER", "You have been auto-opered" },
377 { "NSMSG_AUTO_OPER_ADMIN", "You have been auto-admined" },
379 { "NSEMAIL_ACTIVATION_SUBJECT", "Account verification for %s" },
380 { "NSEMAIL_ACTIVATION_BODY",
381 "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"
383 "To verify your email address and complete the account registration, log on to %1$s and type the following command:\n"
384 "/msg %3$s@%4$s COOKIE %5$s %2$s\n"
385 "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"
386 "/msg %3$s@%4$s AUTH %5$s your-password\n"
387 "(Please remember to fill in 'your-password' with the actual password you gave to us when you registered.)\n"
388 "OR configure Login-On-Connect (see http://www.afternet.org/login-on-connect for instructions) to connect pre-logged in every time.\n"
390 "If you did NOT request this account, you do not need to do anything.\n"
391 "Please contact the %1$s staff if you have questions, and be sure to check our website." },
392 { "NSEMAIL_ACTIVATION_BODY_WEB",
393 "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"
395 "To verify your email address and complete the account registration, visit the following URL:\n"
396 "http://www.afternet.org/index.php?option=com_registration&task=activate&username=%5$s&cookie=%2$s\n"
398 "If you did NOT request this account, you do not need to do anything.\n"
399 "Please contact the %1$s staff if you have questions, and be sure to check our website." },
400 { "NSEMAIL_PASSWORD_CHANGE_SUBJECT", "Password change verification on %s" },
401 { "NSEMAIL_PASSWORD_CHANGE_BODY",
402 "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"
403 "To complete the password change, log on to %1$s and type the following command:\n"
404 "/msg %3$s@%4$s COOKIE %5$s %2$s\n"
405 "If you did NOT request your password to be changed, you do not need to do anything.\n"
406 "Please contact the %1$s staff if you have questions." },
407 { "NSEMAIL_PASSWORD_CHANGE_BODY_WEB",
408 "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"
409 "To complete the password change, click the following URL:\n"
410 "http://www.afternet.org/index.php?option=com_registration&task=passcookie&username=%5$s&cookie=%2$s\n"
411 "If you did NOT request your password to be changed, you do not need to do anything.\n"
412 "Please contact the %1$s staff if you have questions." },
413 { "NSEMAIL_EMAIL_CHANGE_SUBJECT", "Email address change verification for %s" },
414 #ifdef stupid_verify_old_email
415 { "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." },
416 { "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." },
418 { "NSEMAIL_EMAIL_VERIFY_SUBJECT", "Email address verification for %s" },
419 { "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." },
420 { "NSEMAIL_ALLOWAUTH_SUBJECT", "Authentication allowed for %s" },
421 { "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." },
422 { "NSMSG_NOT_VALID_FAKEHOST_DOT", "$b%s$b is not a valid vhost. (needs at least one dot)" },
423 { "NSMSG_NOT_VALID_FAKEHOST_AT", "$b%s$b is not a valid vhost. (it can not have a '@')" },
424 { "NSMSG_DENIED_FAKEHOST_WORD", "Access denied because there's a prohibited word in $b%s$b (%s)." },
425 { "NSMSG_NOT_VALID_FAKEHOST_LEN", "$b%s$b is not a valid vhost. (can only be 63 characters)" },
426 { "NSMSG_NOT_VALID_FAKEHOST_TLD_LEN", "$b%s$b is not a valid vhost. (TLD can only be 4 characters and less)" },
427 { "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." },
428 { "CHECKPASS_YES", "Yes." },
429 { "CHECKPASS_NO", "No." },
430 { "CHECKEMAIL_NOT_SET", "No email set." },
431 { "CHECKEMAIL_YES", "Yes." },
432 { "CHECKEMAIL_NO", "No." },
433 { "NSMSG_DEFCON_NO_NEW_NICKS", "You cannot register new %s at this time, please try again soon" },
437 static void nickserv_reclaim(struct userNode
*user
, struct nick_info
*ni
, enum reclaim_action action
);
438 static void nickserv_reclaim_p(void *data
);
439 static int nickserv_addmask(struct userNode
*user
, struct handle_info
*hi
, const char *mask
);
441 struct nickserv_config nickserv_conf
;
443 /* We have 2^32 unique account IDs to use. */
444 unsigned long int highest_id
= 0;
447 canonicalize_hostmask(char *mask
)
449 char *out
= mask
, *temp
;
450 if ((temp
= strchr(mask
, '!'))) {
452 while (*temp
) *out
++ = *temp
++;
458 static struct handle_note
*
459 nickserv_add_note(const char *setter
, time_t date
, const char *text
)
461 struct handle_note
*note
= calloc(1, sizeof(*note
) + strlen(text
));
463 strncpy(note
->setter
, setter
, sizeof(note
->setter
)-1);
465 memcpy(note
->note
, text
, strlen(text
));
469 static struct handle_info
*
470 register_handle(const char *handle
, const char *passwd
, UNUSED_ARG(unsigned long id
))
472 struct handle_info
*hi
;
474 hi
= calloc(1, sizeof(*hi
));
475 hi
->userlist_style
= nickserv_conf
.default_style
? nickserv_conf
.default_style
: HI_DEFAULT_STYLE
;
476 hi
->announcements
= '?';
477 hi
->handle
= strdup(handle
);
478 safestrncpy(hi
->passwd
, passwd
, sizeof(hi
->passwd
));
480 dict_insert(nickserv_handle_dict
, hi
->handle
, hi
);
486 register_nick(const char *nick
, struct handle_info
*owner
)
488 struct nick_info
*ni
;
489 ni
= malloc(sizeof(struct nick_info
));
490 safestrncpy(ni
->nick
, nick
, sizeof(ni
->nick
));
491 ni
->registered
= now
;
494 ni
->next
= owner
->nicks
;
496 dict_insert(nickserv_nick_dict
, ni
->nick
, ni
);
500 delete_nick(struct nick_info
*ni
)
502 struct nick_info
*last
, *next
;
503 struct userNode
*user
;
504 /* Check to see if we should mark a user as unregistered. */
505 if ((user
= GetUserH(ni
->nick
)) && IsReggedNick(user
)) {
506 user
->modes
&= ~FLAGS_REGNICK
;
509 /* Remove ni from the nick_info linked list. */
510 if (ni
== ni
->owner
->nicks
) {
511 ni
->owner
->nicks
= ni
->next
;
513 last
= ni
->owner
->nicks
;
519 last
->next
= next
->next
;
521 dict_remove(nickserv_nick_dict
, ni
->nick
);
524 static unreg_func_t
*unreg_func_list
;
525 static void **unreg_func_list_extra
;
526 static unsigned int unreg_func_size
= 0, unreg_func_used
= 0;
529 reg_unreg_func(unreg_func_t func
, void *extra
)
531 if (unreg_func_used
== unreg_func_size
) {
532 if (unreg_func_size
) {
533 unreg_func_size
<<= 1;
534 unreg_func_list
= realloc(unreg_func_list
, unreg_func_size
*sizeof(unreg_func_t
));
535 unreg_func_list_extra
= realloc(unreg_func_list_extra
, unreg_func_size
*sizeof(void*));
538 unreg_func_list
= malloc(unreg_func_size
*sizeof(unreg_func_t
));
539 unreg_func_list_extra
= malloc(unreg_func_size
*sizeof(void*));
542 unreg_func_list
[unreg_func_used
] = func
;
543 unreg_func_list_extra
[unreg_func_used
++] = extra
;
547 nickserv_free_cookie(void *data
)
549 struct handle_cookie
*cookie
= data
;
550 if (cookie
->hi
) cookie
->hi
->cookie
= NULL
;
551 if (cookie
->data
) free(cookie
->data
);
556 free_handle_info(void *vhi
)
558 struct handle_info
*hi
= vhi
;
560 free_string_list(hi
->masks
);
561 free_string_list(hi
->sslfps
);
562 free_string_list(hi
->ignores
);
566 delete_nick(hi
->nicks
);
572 timeq_del(hi
->cookie
->expires
, nickserv_free_cookie
, hi
->cookie
, 0);
573 nickserv_free_cookie(hi
->cookie
);
575 if (hi
->email_addr
) {
576 struct handle_info_list
*hil
= dict_find(nickserv_email_dict
, hi
->email_addr
, NULL
);
577 handle_info_list_remove(hil
, hi
);
579 dict_remove(nickserv_email_dict
, hi
->email_addr
);
584 static void set_user_handle_info(struct userNode
*user
, struct handle_info
*hi
, int stamp
);
587 nickserv_unregister_handle(struct handle_info
*hi
, struct userNode
*notify
, struct userNode
*bot
)
590 struct userNode
*uNode
;
593 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
595 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
596 if( (rc
= ldap_delete_account(hi
->handle
)) != LDAP_SUCCESS
) {
598 send_message(notify
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
600 if(rc
!= LDAP_NO_SUCH_OBJECT
)
601 return false; /* if theres noone there to delete, its kinda ok, right ?:) */
606 for (n
=0; n
<unreg_func_used
; n
++)
607 unreg_func_list
[n
](notify
, hi
, unreg_func_list_extra
[n
]);
609 if (nickserv_conf
.sync_log
) {
610 uNode
= GetUserH(hi
->users
->nick
);
614 set_user_handle_info(hi
->users
, NULL
, 0);
617 if (nickserv_conf
.disable_nicks
)
618 send_message(notify
, bot
, "NSMSG_UNREGISTER_SUCCESS", hi
->handle
);
620 send_message(notify
, bot
, "NSMSG_UNREGISTER_NICKS_SUCCESS", hi
->handle
);
623 if (nickserv_conf
.sync_log
)
624 SyncLog("UNREGISTER %s", hi
->handle
);
626 dict_remove(nickserv_handle_dict
, hi
->handle
);
631 get_handle_info(const char *handle
)
633 return dict_find(nickserv_handle_dict
, handle
, 0);
637 get_nick_info(const char *nick
)
639 return nickserv_conf
.disable_nicks
? 0 : dict_find(nickserv_nick_dict
, nick
, 0);
643 find_handle_in_channel(struct chanNode
*channel
, struct handle_info
*handle
, struct userNode
*except
)
648 for (nn
=0; nn
<channel
->members
.used
; ++nn
) {
649 mn
= channel
->members
.list
[nn
];
650 if ((mn
->user
!= except
) && (mn
->user
->handle_info
== handle
))
657 oper_has_access(struct userNode
*user
, struct userNode
*bot
, unsigned int min_level
, unsigned int quiet
) {
658 if (!user
->handle_info
) {
660 send_message(user
, bot
, "MSG_AUTHENTICATE");
664 if (!IsOper(user
) && (!IsHelping(user
) || min_level
)) {
666 send_message(user
, bot
, "NSMSG_NO_ACCESS");
670 if (HANDLE_FLAGGED(user
->handle_info
, OPER_SUSPENDED
)) {
672 send_message(user
, bot
, "MSG_OPER_SUSPENDED");
676 if (user
->handle_info
->opserv_level
< min_level
) {
678 send_message(user
, bot
, "NSMSG_NO_ACCESS");
686 is_valid_handle(const char *handle
)
688 struct userNode
*user
;
689 /* cant register a juped nick/service nick as handle, to prevent confusion */
690 user
= GetUserH(handle
);
691 if (user
&& IsLocal(user
))
693 /* check against maximum length */
694 if (strlen(handle
) > NICKSERV_HANDLE_LEN
)
696 /* for consistency, only allow account names that could be nicks */
697 if (!is_valid_nick(handle
))
699 /* disallow account names that look like bad words */
700 if (opserv_bad_channel(handle
))
702 /* test either regex or containing all valid chars */
703 if (nickserv_conf
.valid_handle_regex_set
) {
704 int err
= regexec(&nickserv_conf
.valid_handle_regex
, handle
, 0, 0, 0);
707 buff
[regerror(err
, &nickserv_conf
.valid_handle_regex
, buff
, sizeof(buff
))] = 0;
708 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
712 return !handle
[strspn(handle
, NICKSERV_VALID_CHARS
)];
717 is_registerable_nick(const char *nick
)
719 struct userNode
*user
;
720 /* cant register a juped nick/service nick as nick, to prevent confusion */
721 user
= GetUserH(nick
);
722 if (user
&& IsLocal(user
))
724 /* for consistency, only allow nicks names that could be nicks */
725 if (!is_valid_nick(nick
))
727 /* disallow nicks that look like bad words */
728 if (opserv_bad_channel(nick
))
731 if (strlen(nick
) > NICKLEN
)
733 /* test either regex or as valid handle */
734 if (nickserv_conf
.valid_nick_regex_set
) {
735 int err
= regexec(&nickserv_conf
.valid_nick_regex
, nick
, 0, 0, 0);
738 buff
[regerror(err
, &nickserv_conf
.valid_nick_regex
, buff
, sizeof(buff
))] = 0;
739 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
745 /* this has been replaced with one in tools.c
748 is_valid_email_addr(const char *email)
750 return strchr(email, '@') != NULL;
756 visible_email_addr(struct userNode
*user
, struct handle_info
*hi
)
758 if (hi
->email_addr
) {
759 if (oper_has_access(user
, nickserv
, nickserv_conf
.email_visible_level
, 1)) {
760 return hi
->email_addr
;
770 smart_get_handle_info(struct userNode
*service
, struct userNode
*user
, const char *name
)
772 struct handle_info
*hi
;
773 struct userNode
*target
;
777 if (!(hi
= get_handle_info(++name
))) {
778 send_message(user
, service
, "MSG_HANDLE_UNKNOWN", name
);
783 if (!(target
= GetUserH(name
))) {
784 send_message(user
, service
, "MSG_NICK_UNKNOWN", name
);
787 if (IsLocal(target
)) {
788 if (IsService(target
))
789 send_message(user
, service
, "NSMSG_USER_IS_SERVICE", target
->nick
);
791 send_message(user
, service
, "MSG_USER_AUTHENTICATE", target
->nick
);
794 if (!(hi
= target
->handle_info
)) {
795 send_message(user
, service
, "MSG_USER_AUTHENTICATE", target
->nick
);
803 oper_outranks(struct userNode
*user
, struct handle_info
*hi
) {
804 if (user
->handle_info
->opserv_level
> hi
->opserv_level
)
806 if (user
->handle_info
->opserv_level
== hi
->opserv_level
) {
807 if ((user
->handle_info
->opserv_level
== 1000)
808 || (user
->handle_info
== hi
)
809 || ((user
->handle_info
->opserv_level
== 0)
810 && !(HANDLE_FLAGGED(hi
, SUPPORT_HELPER
) || HANDLE_FLAGGED(hi
, NETWORK_HELPER
))
811 && HANDLE_FLAGGED(user
->handle_info
, HELPING
))) {
815 send_message(user
, nickserv
, "MSG_USER_OUTRANKED", hi
->handle
);
820 get_victim_oper(struct userNode
*user
, const char *target
)
822 struct handle_info
*hi
;
823 if (!(hi
= smart_get_handle_info(nickserv
, user
, target
)))
825 if (HANDLE_FLAGGED(user
->handle_info
, OPER_SUSPENDED
)) {
826 send_message(user
, nickserv
, "MSG_OPER_SUSPENDED");
829 return oper_outranks(user
, hi
) ? hi
: NULL
;
833 valid_user_for(struct userNode
*user
, struct handle_info
*hi
)
837 /* If no hostmasks on the account, allow it. */
838 if (!hi
->masks
->used
)
840 /* If any hostmask matches, allow it. */
841 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
842 if (user_matches_glob(user
, hi
->masks
->list
[ii
], 0, 0))
844 /* If they are allowauthed to this account, allow it (removing the aa). */
845 if (dict_find(nickserv_allow_auth_dict
, user
->nick
, NULL
) == hi
) {
846 dict_remove(nickserv_allow_auth_dict
, user
->nick
);
849 /* The user is not allowed to use this account. */
854 valid_user_sslfp(struct userNode
*user
, struct handle_info
*hi
)
858 if (!hi
->sslfps
->used
)
863 /* If any SSL fingerprint matches, allow it. */
864 for (ii
=0; ii
<hi
->sslfps
->used
; ii
++)
865 if (!irccasecmp(user
->sslfp
, hi
->sslfps
->list
[ii
]))
868 /* No valid SSL fingerprint found. */
873 is_secure_password(const char *handle
, const char *pass
, struct userNode
*user
)
876 unsigned int cnt_digits
= 0, cnt_upper
= 0, cnt_lower
= 0;
880 if (len
< nickserv_conf
.password_min_length
) {
882 send_message(user
, nickserv
, "NSMSG_PASSWORD_SHORT", nickserv_conf
.password_min_length
);
885 if (!irccasecmp(pass
, handle
)) {
887 send_message(user
, nickserv
, "NSMSG_PASSWORD_ACCOUNT");
890 dict_find(nickserv_conf
.weak_password_dict
, pass
, &p
);
893 send_message(user
, nickserv
, "NSMSG_PASSWORD_DICTIONARY");
896 for (i
=0; i
<len
; i
++) {
897 if (isdigit(pass
[i
]))
899 if (isupper(pass
[i
]))
901 if (islower(pass
[i
]))
904 if ((cnt_lower
< nickserv_conf
.password_min_lower
)
905 || (cnt_upper
< nickserv_conf
.password_min_upper
)
906 || (cnt_digits
< nickserv_conf
.password_min_digits
)) {
908 send_message(user
, nickserv
, "NSMSG_PASSWORD_READABLE", nickserv_conf
.password_min_digits
, nickserv_conf
.password_min_upper
, nickserv_conf
.password_min_lower
);
914 static auth_func_t
*auth_func_list
;
915 static void **auth_func_list_extra
;
916 static unsigned int auth_func_size
= 0, auth_func_used
= 0;
919 reg_auth_func(auth_func_t func
, void *extra
)
921 if (auth_func_used
== auth_func_size
) {
922 if (auth_func_size
) {
923 auth_func_size
<<= 1;
924 auth_func_list
= realloc(auth_func_list
, auth_func_size
*sizeof(auth_func_t
));
925 auth_func_list_extra
= realloc(auth_func_list_extra
, auth_func_size
*sizeof(void*));
928 auth_func_list
= malloc(auth_func_size
*sizeof(auth_func_t
));
929 auth_func_list_extra
= malloc(auth_func_size
*sizeof(void*));
932 auth_func_list
[auth_func_used
] = func
;
933 auth_func_list_extra
[auth_func_used
++] = extra
;
936 static handle_rename_func_t
*rf_list
;
937 static void **rf_list_extra
;
938 static unsigned int rf_list_size
, rf_list_used
;
941 reg_handle_rename_func(handle_rename_func_t func
, void *extra
)
943 if (rf_list_used
== rf_list_size
) {
946 rf_list
= realloc(rf_list
, rf_list_size
*sizeof(rf_list
[0]));
947 rf_list_extra
= realloc(rf_list_extra
, rf_list_size
*sizeof(void*));
950 rf_list
= malloc(rf_list_size
*sizeof(rf_list
[0]));
951 rf_list_extra
= malloc(rf_list_size
*sizeof(void*));
954 rf_list
[rf_list_used
] = func
;
955 rf_list_extra
[rf_list_used
++] = extra
;
959 generate_fakehost(struct handle_info
*handle
)
961 struct userNode
*target
;
962 extern const char *hidden_host_suffix
;
963 static char buffer
[HOSTLEN
+1];
967 if (!handle
->fakehost
) {
968 data
= conf_get_data("server/hidden_host_type", RECDB_QSTRING
);
972 if ((style
== 1) || (style
== 3))
973 snprintf(buffer
, sizeof(buffer
), "%s.%s", handle
->handle
, hidden_host_suffix
);
974 else if (style
== 2) {
975 /* Due to the way fakehost is coded theres no way i can
976 get the exact user, so for now ill just take the first
978 for (target
= handle
->users
; target
; target
= target
->next_authed
)
982 snprintf(buffer
, sizeof(buffer
), "%s", target
->crypthost
);
984 strncpy(buffer
, "none", sizeof(buffer
));
987 } else if (handle
->fakehost
[0] == '.') {
988 /* A leading dot indicates the stored value is actually a title. */
989 snprintf(buffer
, sizeof(buffer
), "%s.%s.%s", handle
->handle
, handle
->fakehost
+1, nickserv_conf
.titlehost_suffix
);
992 return handle
->fakehost
;
996 apply_fakehost(struct handle_info
*handle
)
998 struct userNode
*target
;
1003 fake
= generate_fakehost(handle
);
1004 for (target
= handle
->users
; target
; target
= target
->next_authed
)
1005 assign_fakehost(target
, fake
, 1);
1008 void send_func_list(struct userNode
*user
)
1011 struct handle_info
*old_info
;
1013 old_info
= user
->handle_info
;
1015 for (n
=0; n
<auth_func_used
; n
++)
1016 auth_func_list
[n
](user
, old_info
, auth_func_list_extra
[n
]);
1020 set_user_handle_info(struct userNode
*user
, struct handle_info
*hi
, int stamp
)
1023 struct handle_info
*old_info
;
1025 /* This can happen if somebody uses COOKIE while authed, or if
1026 * they re-auth to their current handle (which is silly, but users
1027 * are like that). */
1028 if (user
->handle_info
== hi
)
1031 if (user
->handle_info
) {
1032 struct userNode
*other
;
1033 struct nick_info
* ni
;
1036 userList_remove(&curr_helpers
, user
);
1038 /* remove from next_authed linked list */
1039 if (user
->handle_info
->users
== user
) {
1040 user
->handle_info
->users
= user
->next_authed
;
1041 } else if (user
->handle_info
->users
!= NULL
) {
1042 for (other
= user
->handle_info
->users
;
1043 other
->next_authed
!= user
;
1044 other
= other
->next_authed
) ;
1045 other
->next_authed
= user
->next_authed
;
1047 /* No users authed to the account - can happen if they get
1048 * killed for authing. */
1050 /* if nobody left on old handle, and they're not an oper, remove !god */
1051 if (!user
->handle_info
->users
&& !user
->handle_info
->opserv_level
)
1052 HANDLE_CLEAR_FLAG(user
->handle_info
, HELPING
);
1053 /* record them as being last seen at this time */
1054 user
->handle_info
->lastseen
= now
;
1055 if ((ni
= get_nick_info(user
->nick
)))
1057 /* and record their hostmask */
1058 snprintf(user
->handle_info
->last_quit_host
, sizeof(user
->handle_info
->last_quit_host
), "%s@%s", user
->ident
, user
->hostname
);
1060 old_info
= user
->handle_info
;
1061 user
->handle_info
= hi
;
1062 if (hi
&& !hi
->users
&& !hi
->opserv_level
)
1063 HANDLE_CLEAR_FLAG(hi
, HELPING
);
1065 /* Call auth handlers */
1066 if (!GetUserH(user
->nick
))
1070 struct nick_info
*ni
;
1072 HANDLE_CLEAR_FLAG(hi
, FROZEN
);
1073 if (nickserv_conf
.warn_clone_auth
) {
1074 struct userNode
*other
;
1075 for (other
= hi
->users
; other
; other
= other
->next_authed
)
1076 send_message(other
, nickserv
, "NSMSG_CLONE_AUTH", user
->nick
, user
->ident
, user
->hostname
);
1079 /* Add this auth to users list of current auths */
1080 user
->next_authed
= hi
->users
;
1083 /* Add to helpers list */
1084 if (IsHelper(user
) && !userList_contains(&curr_helpers
, user
))
1085 userList_append(&curr_helpers
, user
);
1087 /* Set the fakehost */
1088 if (hi
->fakehost
|| old_info
)
1092 #ifdef WITH_PROTOCOL_P10
1093 /* Stamp users with their account name. */
1094 char *id
= hi
->handle
;
1096 const char *id
= "???";
1098 /* Mark all the nicks registered to this
1099 * account as registered nicks
1100 * - Why not just this one? -rubin */
1101 if (!nickserv_conf
.disable_nicks
) {
1102 struct nick_info
*ni2
;
1103 for (ni2
= hi
->nicks
; ni2
; ni2
= ni2
->next
) {
1104 if (!irccasecmp(user
->nick
, ni2
->nick
)) {
1105 user
->modes
|= FLAGS_REGNICK
;
1110 /* send the account to the ircd */
1111 StampUser(user
, id
, hi
->registered
);
1114 /* Stop trying to kick this user off their nick */
1115 if ((ni
= get_nick_info(user
->nick
)) && (ni
->owner
== hi
)) {
1116 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
1120 /* We cannot clear the user's account ID, unfortunately. */
1121 user
->next_authed
= NULL
;
1124 /* Call auth handlers */
1125 if (GetUserH(user
->nick
)) {
1126 for (n
=0; n
<auth_func_used
; n
++) {
1127 auth_func_list
[n
](user
, old_info
, auth_func_list_extra
[n
]);
1134 static struct handle_info
*
1135 nickserv_register(struct userNode
*user
, struct userNode
*settee
, const char *handle
, const char *passwd
, int no_auth
)
1137 struct handle_info
*hi
;
1138 struct nick_info
*ni
;
1139 char crypted
[MD5_CRYPT_LENGTH
] = "";
1141 if ((hi
= dict_find(nickserv_handle_dict
, handle
, NULL
))) {
1143 send_message(user
, nickserv
, "NSMSG_HANDLE_EXISTS", handle
);
1147 if(strlen(handle
) > 30)
1150 send_message(user
, nickserv
, "NSMSG_HANDLE_TOLONG", handle
, 30);
1156 if (!is_secure_password(handle
, passwd
, user
))
1159 cryptpass(passwd
, crypted
);
1162 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1164 rc
= ldap_do_add(handle
, (no_auth
|| !passwd
? NULL
: crypted
), NULL
);
1165 if(LDAP_SUCCESS
!= rc
&& LDAP_ALREADY_EXISTS
!= rc
) {
1167 send_message(user
, nickserv
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
1172 hi
= register_handle(handle
, crypted
, 0);
1173 hi
->masks
= alloc_string_list(1);
1174 hi
->sslfps
= alloc_string_list(1);
1175 hi
->ignores
= alloc_string_list(1);
1177 hi
->language
= lang_C
;
1178 hi
->registered
= now
;
1180 hi
->flags
= HI_DEFAULT_FLAGS
;
1181 if (settee
&& !no_auth
)
1182 set_user_handle_info(settee
, hi
, 1);
1184 if (user
!= settee
) {
1186 send_message(user
, nickserv
, "NSMSG_OREGISTER_H_SUCCESS");
1188 else if (nickserv_conf
.disable_nicks
) {
1190 send_message(user
, nickserv
, "NSMSG_REGISTER_H_SUCCESS");
1193 else if (user
&& (ni
= dict_find(nickserv_nick_dict
, user
->nick
, NULL
))) {
1195 send_message(user
, nickserv
, "NSMSG_PARTIAL_REGISTER");
1200 if (is_registerable_nick(user
->nick
)) {
1201 register_nick(user
->nick
, hi
);
1202 send_message(user
, nickserv
, "NSMSG_REGISTER_HN_SUCCESS");
1206 if (is_registerable_nick(handle
)) {
1207 register_nick(handle
, hi
);
1211 if (settee
&& (user
!= settee
)) {
1213 send_message(settee
, nickserv
, "NSMSG_OREGISTER_VICTIM", user
->nick
, hi
->handle
);
1220 nickserv_bake_cookie(struct handle_cookie
*cookie
)
1222 cookie
->hi
->cookie
= cookie
;
1223 timeq_add(cookie
->expires
, nickserv_free_cookie
, cookie
);
1226 /* Contributed by the great sneep of afternet ;) */
1227 /* Since this gets used in a URL, we want to avoid stuff that confuses
1228 * email clients such as ] and ?. a-z, 0-9 only.
1230 void genpass(char *str
, int len
)
1235 for(i
= 0; i
< len
; i
++)
1239 c
= (char)((float)rand() / (float)RAND_MAX
* (float)256);
1240 } while(!((c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z') || (c
>= '0' && c
<= '9')));
1248 nickserv_make_cookie(struct userNode
*user
, struct handle_info
*hi
, enum cookie_type type
, const char *cookie_data
, int weblink
)
1250 struct handle_cookie
*cookie
;
1251 char subject
[128], body
[4096], *misc
;
1252 const char *netname
, *fmt
;
1256 send_message(user
, nickserv
, "NSMSG_COOKIE_LIVE", hi
->handle
);
1260 cookie
= calloc(1, sizeof(*cookie
));
1262 cookie
->type
= type
;
1263 cookie
->data
= cookie_data
? strdup(cookie_data
) : NULL
;
1265 cookie
->expires
= now
+ nickserv_conf
.cookie_timeout
;
1266 /* Adding dedicated password gen function for more control -Rubin */
1267 genpass(cookie
->cookie
, 10);
1269 *inttobase64(cookie->cookie, rand(), 5);
1270 *inttobase64(cookie->cookie+5, rand(), 5);
1273 netname
= nickserv_conf
.network_name
;
1276 switch (cookie
->type
) {
1278 hi
->passwd
[0] = 0; /* invalidate password */
1279 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_REGISTER");
1280 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_SUBJECT");
1281 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1284 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_BODY_WEB");
1286 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_BODY");
1288 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1291 case PASSWORD_CHANGE
:
1292 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_RESETPASS");
1293 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_SUBJECT");
1294 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1296 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_BODY_WEB");
1298 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_BODY");
1299 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1303 misc
= hi
->email_addr
;
1304 hi
->email_addr
= cookie
->data
;
1305 #ifdef stupid_verify_old_email
1307 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_EMAIL_2");
1308 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_SUBJECT");
1309 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1310 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_BODY_NEW");
1311 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
+COOKIELEN
/2, nickserv
->nick
, self
->name
, hi
->handle
, COOKIELEN
/2);
1312 mail_send(nickserv
, hi
, subject
, body
, 1);
1313 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_BODY_OLD");
1314 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
, COOKIELEN
/2, hi
->email_addr
);
1318 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_EMAIL_1");
1319 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_VERIFY_SUBJECT");
1320 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1321 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_VERIFY_BODY");
1322 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1323 mail_send(nickserv
, hi
, subject
, body
, 1);
1325 #ifdef stupid_verify_old_email
1328 hi
->email_addr
= misc
;
1331 fmt
= handle_find_message(hi
, "NSEMAIL_ALLOWAUTH_SUBJECT");
1332 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1333 fmt
= handle_find_message(hi
, "NSEMAIL_ALLOWAUTH_BODY");
1334 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1335 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_AUTH");
1338 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d in nickserv_make_cookie.", cookie
->type
);
1342 mail_send(nickserv
, hi
, subject
, body
, first_time
);
1343 nickserv_bake_cookie(cookie
);
1347 nickserv_eat_cookie(struct handle_cookie
*cookie
)
1349 cookie
->hi
->cookie
= NULL
;
1350 timeq_del(cookie
->expires
, nickserv_free_cookie
, cookie
, 0);
1351 nickserv_free_cookie(cookie
);
1355 nickserv_free_email_addr(void *data
)
1357 handle_info_list_clean(data
);
1362 nickserv_set_email_addr(struct handle_info
*hi
, const char *new_email_addr
)
1364 struct handle_info_list
*hil
;
1365 /* Remove from old handle_info_list ... */
1366 if (hi
->email_addr
&& (hil
= dict_find(nickserv_email_dict
, hi
->email_addr
, 0))) {
1367 handle_info_list_remove(hil
, hi
);
1368 if (!hil
->used
) dict_remove(nickserv_email_dict
, hil
->tag
);
1369 hi
->email_addr
= NULL
;
1371 /* Add to the new list.. */
1372 if (new_email_addr
) {
1373 if (!(hil
= dict_find(nickserv_email_dict
, new_email_addr
, 0))) {
1374 hil
= calloc(1, sizeof(*hil
));
1375 hil
->tag
= strdup(new_email_addr
);
1376 handle_info_list_init(hil
);
1377 dict_insert(nickserv_email_dict
, hil
->tag
, hil
);
1379 handle_info_list_append(hil
, hi
);
1380 hi
->email_addr
= hil
->tag
;
1384 static NICKSERV_FUNC(cmd_register
)
1387 struct handle_info
*hi
;
1388 const char *email_addr
, *password
;
1389 char syncpass
[MD5_CRYPT_LENGTH
];
1390 int no_auth
, weblink
;
1392 if (checkDefCon(DEFCON_NO_NEW_NICKS
) && !IsOper(user
)) {
1393 reply("NSMSG_DEFCON_NO_NEW_NICKS", nickserv_conf
.disable_nicks
? "accounts" : "nicknames");
1397 if (!IsOper(user
) && !dict_size(nickserv_handle_dict
)) {
1398 /* Require the first handle registered to belong to someone +o. */
1399 reply("NSMSG_REQUIRE_OPER");
1403 if (user
->handle_info
) {
1404 reply("NSMSG_USE_RENAME", user
->handle_info
->handle
);
1408 if (IsRegistering(user
)) {
1409 reply("NSMSG_ALREADY_REGISTERING");
1413 if (IsStamped(user
)) {
1414 /* Unauthenticated users might still have been stamped
1415 previously and could therefore have a hidden host;
1416 do not allow them to register a new account. */
1417 reply("NSMSG_STAMPED_REGISTER");
1421 NICKSERV_MIN_PARMS((unsigned)3 + nickserv_conf
.email_required
);
1423 if(nickserv_conf
.force_handles_lowercase
)
1424 irc_strtolower(argv
[1]);
1425 if (!is_valid_handle(argv
[1])) {
1426 reply("NSMSG_BAD_HANDLE", argv
[1]);
1431 if ((argc
>= 4) && nickserv_conf
.email_enabled
) {
1432 struct handle_info_list
*hil
;
1435 /* Remember email address. */
1436 email_addr
= argv
[3];
1438 /* Check that the email address looks valid.. */
1439 if (!valid_email(email_addr
)) {
1440 reply("NSMSG_BAD_EMAIL_ADDR");
1444 /* .. and that we are allowed to send to it. */
1445 if ((str
= mail_prohibited_address(email_addr
))) {
1446 reply("NSMSG_EMAIL_PROHIBITED", email_addr
, str
);
1450 /* If we do email verify, make sure we don't spam the address. */
1451 if ((hil
= dict_find(nickserv_email_dict
, email_addr
, NULL
))) {
1453 for (nn
=0; nn
<hil
->used
; nn
++) {
1454 if (hil
->list
[nn
]->cookie
) {
1455 reply("NSMSG_EMAIL_UNACTIVATED");
1459 if (hil
->used
>= nickserv_conf
.handles_per_email
) {
1460 reply("NSMSG_EMAIL_OVERUSED");
1473 /* Webregister hack - send URL instead of IRC cookie
1476 if((argc
>= 5) && !strcmp(argv
[4],"WEBLINK"))
1480 if (!(hi
= nickserv_register(user
, user
, argv
[1], password
, no_auth
)))
1482 /* Add any masks they should get. */
1483 if (nickserv_conf
.default_hostmask
) {
1484 string_list_append(hi
->masks
, strdup("*@*"));
1486 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
1487 if (irc_in_addr_is_valid(user
->ip
) && !irc_pton(&ip
, NULL
, user
->hostname
))
1488 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_BYIP
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
1491 /* If they're the first to register, give them level 1000. */
1492 if (dict_size(nickserv_handle_dict
) == 1) {
1493 hi
->opserv_level
= 1000;
1494 reply("NSMSG_ROOT_HANDLE", argv
[1]);
1497 /* Set their email address. */
1500 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1502 if((rc
= ldap_do_modify(hi
->handle
, NULL
, email_addr
)) != LDAP_SUCCESS
) {
1503 /* Falied to update email in ldap, but still
1504 * updated it here.. what should we do? */
1505 reply("NSMSG_LDAP_FAIL_EMAIL", ldap_err2string(rc
));
1507 nickserv_set_email_addr(hi
, email_addr
);
1511 nickserv_set_email_addr(hi
, email_addr
);
1514 nickserv_set_email_addr(hi
, email_addr
);
1518 /* If they need to do email verification, tell them. */
1520 nickserv_make_cookie(user
, hi
, ACTIVATION
, hi
->passwd
, weblink
);
1522 /* Set registering flag.. */
1523 user
->modes
|= FLAGS_REGISTERING
;
1525 if (nickserv_conf
.sync_log
) {
1526 cryptpass(password
, syncpass
);
1528 * An 0 is only sent if theres no email address. Thios should only happen if email functions are
1529 * disabled which they wont be for us. Email Required MUST be set on if you are using this.
1532 SyncLog("REGISTER %s %s %s %s", hi
->handle
, syncpass
, email_addr
? email_addr
: "0", user
->info
);
1535 /* this wont work if email is required .. */
1536 process_adduser_pending(user
);
1541 static NICKSERV_FUNC(cmd_oregister
)
1543 struct userNode
*settee
= NULL
;
1544 struct handle_info
*hi
;
1545 char* account
= NULL
;
1551 NICKSERV_MIN_PARMS(2);
1555 if(nickserv_conf
.force_handles_lowercase
)
1556 irc_strtolower(account
);
1557 if (!is_valid_handle(argv
[1])) {
1558 reply("NSMSG_BAD_HANDLE", argv
[1]);
1561 if (nickserv_conf
.email_required
) {
1562 NICKSERV_MIN_PARMS(3);
1564 if (argc
> 4) {/* take: "acct pass email mask nick" or "acct pass email mask" or "acct pass email nick" */
1565 if (strchr(argv
[4], '@'))
1575 if (argc
> 3) {/* take: "account pass mask nick" or "account pass mask" or "account pass nick" */
1576 if (strchr(argv
[3], '@'))
1585 /* If they passed a nick, look for that user.. */
1586 if (nick
&& !(settee
= GetUserH(nick
))) {
1587 reply("MSG_NICK_UNKNOWN", argv
[4]);
1590 /* If the setee is already authed, we cant add a 2nd account for them.. */
1591 if (settee
&& settee
->handle_info
) {
1592 reply("NSMSG_USER_PREV_AUTH", settee
->nick
);
1595 /* If there is no default mask in the conf, and they didn't pass a mask,
1596 * but we did find a user by nick, generate the mask */
1598 if (nickserv_conf
.default_hostmask
)
1601 mask
= generate_hostmask(settee
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
1603 reply("NSMSG_REGISTER_BAD_NICKMASK");
1608 if (!(hi
= nickserv_register(user
, settee
, account
, pass
, 0))) {
1609 return 0; /* error reply handled by above */
1613 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1615 if((rc
= ldap_do_modify(hi
->handle
, NULL
, email
)) != LDAP_SUCCESS
) {
1616 /* Falied to update email in ldap, but still
1617 * updated it here.. what should we do? */
1618 reply("NSMSG_LDAP_FAIL_EMAIL", ldap_err2string(rc
));
1620 nickserv_set_email_addr(hi
, email
);
1624 nickserv_set_email_addr(hi
, email
);
1627 nickserv_set_email_addr(hi
, email
);
1631 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
1632 if (mask_canonicalized
)
1633 string_list_append(hi
->masks
, mask_canonicalized
);
1638 if (nickserv_conf
.sync_log
)
1639 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, email
? email
: "@", user
->info
); /* Send just @ for email if none */
1644 nickserv_ignore(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, char *mask
)
1647 struct userNode
*target
;
1648 char *new_mask
= strdup(pretty_mask(mask
));
1649 for (i
=0; i
<hi
->ignores
->used
; i
++) {
1650 if (!irccasecmp(new_mask
, hi
->ignores
->list
[i
])) {
1651 reply("NSMSG_ADDIGNORE_ALREADY", new_mask
);
1656 string_list_append(hi
->ignores
, new_mask
);
1657 reply("NSMSG_ADDIGNORE_SUCCESS", new_mask
);
1659 for (target
= hi
->users
; target
; target
= target
->next_authed
) {
1660 irc_silence(target
, new_mask
, 1);
1665 static NICKSERV_FUNC(cmd_addignore
)
1667 NICKSERV_MIN_PARMS(2);
1669 return nickserv_ignore(cmd
, user
, user
->handle_info
, argv
[1]);
1672 static NICKSERV_FUNC(cmd_oaddignore
)
1674 struct handle_info
*hi
;
1676 NICKSERV_MIN_PARMS(3);
1677 if (!(hi
= get_victim_oper(user
, argv
[1])))
1680 return nickserv_ignore(cmd
, user
, hi
, argv
[2]);
1684 nickserv_delignore(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, char *del_mask
)
1687 struct userNode
*target
;
1688 char *pmask
= strdup(pretty_mask(del_mask
));
1689 for (i
=0; i
<hi
->ignores
->used
; i
++) {
1690 if (!strcmp(pmask
, hi
->ignores
->list
[i
]) || !strcmp(del_mask
, hi
->ignores
->list
[i
])) {
1691 char *old_mask
= hi
->ignores
->list
[i
];
1692 hi
->ignores
->list
[i
] = hi
->ignores
->list
[--hi
->ignores
->used
];
1693 reply("NSMSG_DELMASK_SUCCESS", old_mask
);
1694 for (target
= hi
->users
; target
; target
= target
->next_authed
) {
1695 irc_silence(target
, old_mask
, 0);
1702 reply("NSMSG_DELMASK_NOT_FOUND");
1706 static NICKSERV_FUNC(cmd_delignore
)
1708 NICKSERV_MIN_PARMS(2);
1709 return nickserv_delignore(cmd
, user
, user
->handle_info
, argv
[1]);
1712 static NICKSERV_FUNC(cmd_odelignore
)
1714 struct handle_info
*hi
;
1715 NICKSERV_MIN_PARMS(3);
1716 if (!(hi
= get_victim_oper(user
, argv
[1])))
1718 return nickserv_delignore(cmd
, user
, hi
, argv
[2]);
1721 static NICKSERV_FUNC(cmd_handleinfo
)
1724 unsigned int i
, pos
=0, herelen
;
1725 struct userNode
*target
, *next_un
;
1726 struct handle_info
*hi
;
1727 const char *nsmsg_none
;
1730 if (!(hi
= user
->handle_info
)) {
1731 reply("NSMSG_MUST_AUTH");
1734 } else if (!(hi
= modcmd_get_handle_info(user
, argv
[1]))) {
1738 nsmsg_none
= handle_find_message(hi
, "MSG_NONE");
1739 reply("NSMSG_HANDLEINFO_ON", hi
->handle
);
1741 reply("NSMSG_HANDLEINFO_REGGED", ctime(&hi
->registered
));
1744 intervalString(buff
, now
- hi
->lastseen
, user
->handle_info
);
1745 reply("NSMSG_HANDLEINFO_LASTSEEN", buff
);
1747 reply("NSMSG_HANDLEINFO_LASTSEEN_NOW");
1750 reply("NSMSG_HANDLEINFO_INFOLINE", (hi
->infoline
? hi
->infoline
: nsmsg_none
));
1751 if (HANDLE_FLAGGED(hi
, FROZEN
))
1752 reply("NSMSG_HANDLEINFO_VACATION");
1754 if (oper_has_access(user
, cmd
->parent
->bot
, 0, 1)) {
1755 struct do_not_register
*dnr
;
1756 if ((dnr
= chanserv_is_dnr(NULL
, hi
)))
1757 reply("NSMSG_HANDLEINFO_DNR", dnr
->setter
, dnr
->reason
);
1758 if ((user
->handle_info
->opserv_level
< 900) && !oper_outranks(user
, hi
))
1760 } else if (hi
!= user
->handle_info
) {
1761 reply("NSMSG_HANDLEINFO_END");
1766 reply("NSMSG_HANDLEINFO_KARMA", hi
->karma
);
1768 if (nickserv_conf
.email_enabled
)
1769 reply("NSMSG_HANDLEINFO_EMAIL_ADDR", visible_email_addr(user
, hi
));
1773 switch (hi
->cookie
->type
) {
1774 case ACTIVATION
: type
= "NSMSG_HANDLEINFO_COOKIE_ACTIVATION"; break;
1775 case PASSWORD_CHANGE
: type
= "NSMSG_HANDLEINFO_COOKIE_PASSWORD"; break;
1776 case EMAIL_CHANGE
: type
= "NSMSG_HANDLEINFO_COOKIE_EMAIL"; break;
1777 case ALLOWAUTH
: type
= "NSMSG_HANDLEINFO_COOKIE_ALLOWAUTH"; break;
1778 default: type
= "NSMSG_HANDLEINFO_COOKIE_UNKNOWN"; break;
1781 if (IsOper(user
) && (hi
->cookie
->type
== EMAIL_CHANGE
))
1782 reply("NSMSG_HANDLEINFO_COOKIE_EMAIL_DATA", hi
->cookie
->data
);
1786 unsigned long flen
= 1;
1787 char flags
[34]; /* 32 bits possible plus '+' and '\0' */
1789 for (i
=0, flen
=1; handle_flags
[i
]; i
++)
1790 if (hi
->flags
& 1 << i
)
1791 flags
[flen
++] = handle_flags
[i
];
1793 reply("NSMSG_HANDLEINFO_FLAGS", flags
);
1795 reply("NSMSG_HANDLEINFO_FLAGS", nsmsg_none
);
1798 if (HANDLE_FLAGGED(hi
, SUPPORT_HELPER
)
1799 || HANDLE_FLAGGED(hi
, NETWORK_HELPER
)
1800 || (hi
->opserv_level
> 0)) {
1801 reply("NSMSG_HANDLEINFO_EPITHET", (hi
->epithet
? hi
->epithet
: nsmsg_none
));
1804 if (IsHelping(user
) || IsOper(user
))
1809 strftime(date
, 64, "%b %d %Y", localtime(&hi
->note
->date
));
1810 reply("NSMSG_HANDLEINFO_NOTE", hi
->note
->setter
, date
, hi
->note
->note
);
1815 reply("NSMSG_HANDLEINFO_FAKEHOST", (hi
->fakehost
? hi
->fakehost
: handle_find_message(hi
, "MSG_NONE")));
1817 if (hi
->last_quit_host
[0])
1818 reply("NSMSG_HANDLEINFO_LAST_HOST", hi
->last_quit_host
);
1820 reply("NSMSG_HANDLEINFO_LAST_HOST_UNKNOWN");
1822 if (nickserv_conf
.disable_nicks
) {
1823 /* nicks disabled; don't show anything about registered nicks */
1824 } else if (hi
->nicks
) {
1825 struct nick_info
*ni
, *next_ni
;
1826 for (ni
= hi
->nicks
; ni
; ni
= next_ni
) {
1827 herelen
= strlen(ni
->nick
);
1828 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1830 goto print_nicks_buff
;
1834 memcpy(buff
+pos
, ni
->nick
, herelen
);
1835 pos
+= herelen
; buff
[pos
++] = ' ';
1839 reply("NSMSG_HANDLEINFO_NICKS", buff
);
1844 reply("NSMSG_HANDLEINFO_NICKS", nsmsg_none
);
1847 if (hi
->masks
->used
) {
1848 for (i
=0; i
< hi
->masks
->used
; i
++) {
1849 herelen
= strlen(hi
->masks
->list
[i
]);
1850 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1852 goto print_mask_buff
;
1854 memcpy(buff
+pos
, hi
->masks
->list
[i
], herelen
);
1855 pos
+= herelen
; buff
[pos
++] = ' ';
1856 if (i
+1 == hi
->masks
->used
) {
1859 reply("NSMSG_HANDLEINFO_MASKS", buff
);
1864 reply("NSMSG_HANDLEINFO_MASKS", nsmsg_none
);
1867 if (hi
->sslfps
->used
) {
1868 for (i
=0; i
< hi
->sslfps
->used
; i
++) {
1869 herelen
= strlen(hi
->sslfps
->list
[i
]);
1870 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1872 goto print_sslfp_buff
;
1874 memcpy(buff
+pos
, hi
->sslfps
->list
[i
], herelen
);
1875 pos
+= herelen
; buff
[pos
++] = ' ';
1876 if (i
+1 == hi
->sslfps
->used
) {
1879 reply("NSMSG_HANDLEINFO_SSLFPS", buff
);
1884 reply("NSMSG_HANDLEINFO_SSLFPS", nsmsg_none
);
1887 if (hi
->ignores
->used
) {
1888 for (i
=0; i
< hi
->ignores
->used
; i
++) {
1889 herelen
= strlen(hi
->ignores
->list
[i
]);
1890 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1892 goto print_ignore_buff
;
1894 memcpy(buff
+pos
, hi
->ignores
->list
[i
], herelen
);
1895 pos
+= herelen
; buff
[pos
++] = ' ';
1896 if (i
+1 == hi
->ignores
->used
) {
1899 reply("NSMSG_HANDLEINFO_IGNORES", buff
);
1904 reply("NSMSG_HANDLEINFO_IGNORES", nsmsg_none
);
1908 struct userData
*chan
, *next
;
1911 for (chan
= hi
->channels
; chan
; chan
= next
) {
1912 next
= chan
->u_next
;
1913 name
= chan
->channel
->channel
->name
;
1914 herelen
= strlen(name
);
1915 if (pos
+ herelen
+ 7 > ArrayLength(buff
)) {
1917 goto print_chans_buff
;
1919 if (IsUserSuspended(chan
))
1921 pos
+= sprintf(buff
+pos
, "%s:%s ", user_level_name_from_level(chan
->access
), name
);
1925 reply("NSMSG_HANDLEINFO_CHANNELS", buff
);
1930 reply("NSMSG_HANDLEINFO_CHANNELS", nsmsg_none
);
1933 for (target
= hi
->users
; target
; target
= next_un
) {
1934 herelen
= strlen(target
->nick
);
1935 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1937 goto print_cnick_buff
;
1939 next_un
= target
->next_authed
;
1941 memcpy(buff
+pos
, target
->nick
, herelen
);
1942 pos
+= herelen
; buff
[pos
++] = ' ';
1946 reply("NSMSG_HANDLEINFO_CURRENT", buff
);
1951 reply("NSMSG_HANDLEINFO_END");
1952 return 1 | ((hi
!= user
->handle_info
) ? CMD_LOG_STAFF
: 0);
1955 static NICKSERV_FUNC(cmd_userinfo
)
1957 struct userNode
*target
;
1959 NICKSERV_MIN_PARMS(2);
1960 if (!(target
= GetUserH(argv
[1]))) {
1961 reply("MSG_NICK_UNKNOWN", argv
[1]);
1964 if (target
->handle_info
)
1965 reply("NSMSG_USERINFO_AUTHED_AS", target
->nick
, target
->handle_info
->handle
);
1967 reply("NSMSG_USERINFO_NOT_AUTHED", target
->nick
);
1971 static NICKSERV_FUNC(cmd_nickinfo
)
1973 struct nick_info
*ni
;
1976 NICKSERV_MIN_PARMS(2);
1977 if (!(ni
= get_nick_info(argv
[1]))) {
1978 reply("MSG_NICK_UNKNOWN", argv
[1]);
1982 reply("NSMSG_NICKINFO_ON", ni
->nick
);
1984 reply("NSMSG_NICKINFO_REGGED", ctime(&ni
->registered
));
1986 if (!GetUserH(ni
->nick
)) {
1987 intervalString(buff
, now
- ni
->lastseen
, user
->handle_info
);
1988 reply("NSMSG_NICKINFO_LASTSEEN", buff
);
1990 reply("NSMSG_NICKINFO_LASTSEEN_NOW");
1993 reply("NSMSG_NICKINFO_OWNER", ni
->owner
->handle
);
1995 reply("NSMSG_NICKINFO_END");
2000 static NICKSERV_FUNC(cmd_rename_handle
)
2002 struct handle_info
*hi
;
2003 struct userNode
*uNode
;
2007 NICKSERV_MIN_PARMS(3);
2008 if(nickserv_conf
.force_handles_lowercase
)
2009 irc_strtolower(argv
[2]);
2010 if (!(hi
= get_victim_oper(user
, argv
[1])))
2012 if (!is_valid_handle(argv
[2])) {
2013 reply("NSMSG_FAIL_RENAME", argv
[1], argv
[2]);
2016 if (get_handle_info(argv
[2])) {
2017 reply("NSMSG_HANDLE_EXISTS", argv
[2]);
2020 if(strlen(argv
[2]) > 30)
2022 reply("NMSG_HANDLE_TOLONG", argv
[2], 30);
2026 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2028 if( (rc
= ldap_rename_account(hi
->handle
, argv
[2])) != LDAP_SUCCESS
) {
2029 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2035 dict_remove2(nickserv_handle_dict
, old_handle
= hi
->handle
, 1);
2036 hi
->handle
= strdup(argv
[2]);
2037 dict_insert(nickserv_handle_dict
, hi
->handle
, hi
);
2038 for (nn
=0; nn
<rf_list_used
; nn
++)
2039 rf_list
[nn
](hi
, old_handle
, rf_list_extra
[nn
]);
2041 if (nickserv_conf
.sync_log
) {
2042 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
2043 irc_rename(uNode
, hi
->handle
);
2045 SyncLog("RENAME %s %s", old_handle
, hi
->handle
);
2048 reply("NSMSG_HANDLE_CHANGED", old_handle
, hi
->handle
);
2049 global_message_args(MESSAGE_RECIPIENT_OPERS
, "NSMSG_ACCOUNT_RENAMED",
2050 user
->handle_info
->handle
, old_handle
, hi
->handle
);
2056 static failpw_func_t
*failpw_func_list
;
2057 static void **failpw_func_list_extra
;
2058 static unsigned int failpw_func_size
= 0, failpw_func_used
= 0;
2061 reg_failpw_func(failpw_func_t func
, void *extra
)
2063 if (failpw_func_used
== failpw_func_size
) {
2064 if (failpw_func_size
) {
2065 failpw_func_size
<<= 1;
2066 failpw_func_list
= realloc(failpw_func_list
, failpw_func_size
*sizeof(failpw_func_t
));
2067 failpw_func_list_extra
= realloc(failpw_func_list_extra
, failpw_func_size
*sizeof(void*));
2069 failpw_func_size
= 8;
2070 failpw_func_list
= malloc(failpw_func_size
*sizeof(failpw_func_t
));
2071 failpw_func_list_extra
= malloc(failpw_func_size
*sizeof(void*));
2074 failpw_func_list
[failpw_func_used
] = func
;
2075 failpw_func_list_extra
[failpw_func_used
++] = extra
;
2079 * Return hi for the first handle that has a matching SSL fingerprint.
2081 struct handle_info
*find_handleinfo_by_sslfp(char *sslfp
)
2084 struct handle_info
*hi
;
2085 unsigned int ii
= 0;;
2087 for (it
= dict_first(nickserv_handle_dict
); it
; it
= iter_next(it
)) {
2089 for (ii
=0; ii
<hi
->sslfps
->used
; ii
++) {
2090 if (!irccasecmp(sslfp
, hi
->sslfps
->list
[ii
])) {
2100 * Return hi if the handle/pass pair matches, NULL if it doesnt.
2102 * called by nefariouses enhanced AC login-on-connect code
2105 struct handle_info
*loc_auth(char *sslfp
, char *handle
, char *password
, char *userhost
)
2107 int wildmask
= 0, auth
= 0;
2108 int used
, maxlogins
;
2110 struct handle_info
*hi
= NULL
;
2111 struct userNode
*other
;
2113 int ldap_result
= LDAP_SUCCESS
;
2118 hi
= dict_find(nickserv_handle_dict
, handle
, NULL
);
2119 if (!hi
&& (sslfp
!= NULL
)) {
2120 hi
= find_handleinfo_by_sslfp(sslfp
);
2121 if (!handle
&& (hi
!= NULL
))
2122 handle
= hi
->handle
;
2126 if (nickserv_conf
.ldap_enable
&& (password
!= NULL
)) {
2127 ldap_result
= ldap_check_auth(handle
, password
);
2128 if (!hi
&& (ldap_result
!= LDAP_SUCCESS
))
2130 if (ldap_result
== LDAP_SUCCESS
) {
2131 /* Mark auth as successful */
2135 if (!hi
&& (ldap_result
== LDAP_SUCCESS
) && nickserv_conf
.ldap_autocreate
) {
2136 /* user not found, but authed to ldap successfully..
2137 * create the account.
2142 /* Add a *@* mask */
2143 /* TODO if userhost is not null, build mask based on that. */
2144 if(nickserv_conf
.default_hostmask
)
2147 return NULL
; /* They dont have a *@* mask so they can't loc */
2149 if(!(hi
= nickserv_register(NULL
, NULL
, handle
, password
, 0))) {
2150 return 0; /* couldn't add the user for some reason */
2153 if((rc
= ldap_get_user_info(handle
, &email
) != LDAP_SUCCESS
))
2155 if(nickserv_conf
.email_required
) {
2160 nickserv_set_email_addr(hi
, email
);
2164 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
2165 string_list_append(hi
->masks
, mask_canonicalized
);
2167 if(nickserv_conf
.sync_log
)
2168 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, "@", handle
);
2173 /* hi should now be a valid handle, if not return NULL */
2178 if (password
&& *password
&& !nickserv_conf
.ldap_enable
) {
2180 if (password
&& *password
) {
2182 if (checkpass(password
, hi
->passwd
))
2186 if (!auth
&& sslfp
&& *sslfp
&& hi
->sslfps
->used
) {
2187 /* If any SSL fingerprint matches, allow it. */
2188 for (ii
=0; ii
<hi
->sslfps
->used
; ii
++) {
2189 if (!irccasecmp(sslfp
, hi
->sslfps
->list
[ii
])) {
2196 /* Auth should have succeeded by this point */
2200 /* We don't know the users hostname, or anything because they
2201 * havn't registered yet. So we can only allow LOC if your
2202 * account has *@* as a hostmask.
2204 * UPDATE: New nefarious LOC supports u@h
2209 char *realhost
= NULL
;
2216 buf
= strdup(userhost
);
2219 for (c
= buf
; *c
; c
++) {
2220 if ((realhost
== NULL
) && (*c
== '@')) {
2227 } else if (bracket
&& (ip
== NULL
) && (*c
== ']')) {
2230 } else if (!bracket
&& (ip
== NULL
) && (*c
== ':')) {
2237 log_module(NS_LOG
, LOG_DEBUG
, "LOC: ident=%s host=%s ip=%s", ident
, realhost
, ip
);
2239 if(!ip
|| !realhost
|| !ident
) {
2241 return NULL
; /* Invalid AC request, just quit */
2243 uh
= malloc(strlen(userhost
));
2244 ui
= malloc(strlen(userhost
));
2245 sprintf(uh
, "%s@%s", ident
, realhost
);
2246 sprintf(ui
, "%s@%s", ident
, ip
);
2247 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
2249 if(match_ircglob(uh
, hi
->masks
->list
[ii
])
2250 || match_ircglob(ui
, hi
->masks
->list
[ii
]))
2262 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
2264 if (!strcmp(hi
->masks
->list
[ii
], "*@*"))
2274 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2278 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
2279 for (used
= 0, other
= hi
->users
; other
; other
= other
->next_authed
) {
2280 if (++used
>= maxlogins
) {
2284 /* TODO - Add LOGGING to this function so LOC's are logged.. */
2288 static NICKSERV_FUNC(cmd_auth
)
2290 int pw_arg
, used
, maxlogins
;
2291 struct handle_info
*hi
;
2294 struct userNode
*other
;
2296 int ldap_result
= LDAP_OTHER
;
2300 if (user
->handle_info
) {
2301 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2304 if (IsStamped(user
)) {
2305 /* Unauthenticated users might still have been stamped
2306 previously and could therefore have a hidden host;
2307 do not allow them to authenticate. */
2308 reply("NSMSG_STAMPED_AUTH");
2315 hi
= dict_find(nickserv_handle_dict
, argv
[1], NULL
);
2316 } else if (argc
== 2) {
2319 if (nickserv_conf
.disable_nicks
) {
2320 hi
= get_handle_info(user
->nick
);
2322 /* try to look up their handle from their nick */
2323 /* TODO: handle ldap auth on nickserv style networks, too */
2324 struct nick_info
*ni
;
2325 ni
= get_nick_info(user
->nick
);
2327 reply("NSMSG_NICK_NOT_REGISTERED", user
->nick
);
2333 handle
= hi
->handle
;
2335 handle
= user
->nick
;
2338 reply("MSG_MISSING_PARAMS", argv
[0]);
2339 svccmd_send_help_brief(user
, nickserv
, cmd
);
2344 if(strchr(argv
[1], '<') || strchr(handle
, '>')) {
2345 reply("NSMSG_NO_ANGLEBRACKETS");
2348 if (!is_valid_handle(handle
)) {
2349 reply("NSMSG_BAD_HANDLE", handle
);
2353 if(nickserv_conf
.ldap_enable
) {
2354 ldap_result
= ldap_check_auth(handle
, passwd
);
2355 /* Get the users email address and update it */
2356 if(ldap_result
== LDAP_SUCCESS
) {
2358 if((rc
= ldap_get_user_info(handle
, &email
) != LDAP_SUCCESS
))
2360 if(nickserv_conf
.email_required
) {
2361 reply("NSMSG_LDAP_FAIL_GET_EMAIL", ldap_err2string(rc
));
2366 else if(ldap_result
!= LDAP_INVALID_CREDENTIALS
) {
2367 reply("NSMSG_LDAP_FAIL", ldap_err2string(ldap_result
));
2375 if(nickserv_conf
.ldap_enable
&& ldap_result
== LDAP_SUCCESS
&& nickserv_conf
.ldap_autocreate
) {
2376 /* user not found, but authed to ldap successfully..
2377 * create the account.
2380 if(!(hi
= nickserv_register(user
, user
, argv
[1], argv
[2], 0))) {
2381 reply("NSMSG_UNABLE_TO_ADD");
2382 return 0; /* couldn't add the user for some reason */
2384 /* Add a *@* mask */
2385 if(nickserv_conf
.default_hostmask
)
2388 mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2391 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
2392 string_list_append(hi
->masks
, mask_canonicalized
);
2395 nickserv_set_email_addr(hi
, email
);
2398 if(nickserv_conf
.sync_log
)
2399 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, email
? email
: "@", user
->info
);
2403 reply("NSMSG_HANDLE_NOT_FOUND");
2409 /* Responses from here on look up the language used by the handle they asked about. */
2410 if (!valid_user_for(user
, hi
)) {
2411 if (hi
->email_addr
&& nickserv_conf
.email_enabled
)
2412 send_message_type(4, user
, cmd
->parent
->bot
,
2413 handle_find_message(hi
, "NSMSG_USE_AUTHCOOKIE"),
2416 send_message_type(4, user
, cmd
->parent
->bot
,
2417 handle_find_message(hi
, "NSMSG_HOSTMASK_INVALID"),
2419 argv
[pw_arg
] = "BADMASK";
2423 if(( ( nickserv_conf
.ldap_enable
&& ldap_result
== LDAP_INVALID_CREDENTIALS
) ||
2424 ( (!nickserv_conf
.ldap_enable
) && (!checkpass(passwd
, hi
->passwd
)) ) ) && !valid_user_sslfp(user
, hi
)) {
2426 if (!checkpass(passwd
, hi
->passwd
) && !valid_user_sslfp(user
, hi
)) {
2429 send_message_type(4, user
, cmd
->parent
->bot
,
2430 handle_find_message(hi
, "NSMSG_PASSWORD_INVALID"));
2431 argv
[pw_arg
] = "BADPASS";
2432 for (n
=0; n
<failpw_func_used
; n
++)
2433 failpw_func_list
[n
](user
, hi
, failpw_func_list_extra
[n
]);
2434 if (nickserv_conf
.autogag_enabled
) {
2435 if (!user
->auth_policer
.params
) {
2436 user
->auth_policer
.last_req
= now
;
2437 user
->auth_policer
.params
= nickserv_conf
.auth_policer_params
;
2439 if (!policer_conforms(&user
->auth_policer
, now
, 1.0)) {
2441 hostmask
= generate_hostmask(user
, GENMASK_STRICT_HOST
|GENMASK_BYIP
|GENMASK_NO_HIDING
);
2442 log_module(NS_LOG
, LOG_INFO
, "%s auto-gagged for repeated password guessing.", hostmask
);
2443 gag_create(hostmask
, nickserv
->nick
, "Repeated password guessing.", now
+nickserv_conf
.autogag_duration
);
2445 argv
[pw_arg
] = "GAGGED";
2450 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2451 send_message_type(4, user
, cmd
->parent
->bot
,
2452 handle_find_message(hi
, "NSMSG_HANDLE_SUSPENDED"));
2453 argv
[pw_arg
] = "SUSPENDED";
2456 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
2457 for (used
= 0, other
= hi
->users
; other
; other
= other
->next_authed
) {
2458 if (++used
>= maxlogins
) {
2459 send_message_type(4, user
, cmd
->parent
->bot
,
2460 handle_find_message(hi
, "NSMSG_MAX_LOGINS"),
2462 argv
[pw_arg
] = "MAXLOGINS";
2467 set_user_handle_info(user
, hi
, 1);
2468 if (nickserv_conf
.email_required
&& !hi
->email_addr
)
2469 reply("NSMSG_PLEASE_SET_EMAIL");
2470 if (!is_secure_password(hi
->handle
, passwd
, NULL
))
2471 reply("NSMSG_WEAK_PASSWORD");
2472 if (hi
->passwd
[0] != '$')
2473 cryptpass(passwd
, hi
->passwd
);
2475 /* If a channel was waiting for this user to auth,
2476 * finish adding them */
2477 process_adduser_pending(user
);
2479 reply("NSMSG_AUTH_SUCCESS");
2482 /* Set +x if autohide is on */
2483 if(HANDLE_FLAGGED(hi
, AUTOHIDE
))
2484 irc_umode(user
, "+x");
2486 if (!hi
->masks
->used
) {
2488 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
2489 if (irc_in_addr_is_valid(user
->ip
) && irc_pton(&ip
, NULL
, user
->hostname
))
2490 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_BYIP
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
2493 /* Wipe out the pass for the logs */
2494 argv
[pw_arg
] = "****";
2498 static allowauth_func_t
*allowauth_func_list
;
2499 static void **allowauth_func_list_extra
;
2500 static unsigned int allowauth_func_size
= 0, allowauth_func_used
= 0;
2503 reg_allowauth_func(allowauth_func_t func
, void *extra
)
2505 if (allowauth_func_used
== allowauth_func_size
) {
2506 if (allowauth_func_size
) {
2507 allowauth_func_size
<<= 1;
2508 allowauth_func_list
= realloc(allowauth_func_list
, allowauth_func_size
*sizeof(allowauth_func_t
));
2509 allowauth_func_list_extra
= realloc(allowauth_func_list_extra
, allowauth_func_size
*sizeof(void*));
2511 allowauth_func_size
= 8;
2512 allowauth_func_list
= malloc(allowauth_func_size
*sizeof(allowauth_func_t
));
2513 allowauth_func_list_extra
= malloc(allowauth_func_size
*sizeof(void*));
2516 allowauth_func_list
[allowauth_func_used
] = func
;
2517 allowauth_func_list_extra
[allowauth_func_used
++] = extra
;
2520 static NICKSERV_FUNC(cmd_allowauth
)
2522 struct userNode
*target
;
2523 struct handle_info
*hi
;
2526 NICKSERV_MIN_PARMS(2);
2527 if (!(target
= GetUserH(argv
[1]))) {
2528 reply("MSG_NICK_UNKNOWN", argv
[1]);
2531 if (target
->handle_info
) {
2532 reply("NSMSG_USER_PREV_AUTH", target
->nick
);
2535 if (IsStamped(target
)) {
2536 /* Unauthenticated users might still have been stamped
2537 previously and could therefore have a hidden host;
2538 do not allow them to authenticate to an account. */
2539 reply("NSMSG_USER_PREV_STAMP", target
->nick
);
2544 else if (!(hi
= get_handle_info(argv
[2]))) {
2545 reply("MSG_HANDLE_UNKNOWN", argv
[2]);
2549 if (hi
->opserv_level
> user
->handle_info
->opserv_level
) {
2550 reply("MSG_USER_OUTRANKED", hi
->handle
);
2553 if (((hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
))
2554 || (hi
->opserv_level
> 0))
2555 && ((argc
< 4) || irccasecmp(argv
[3], "staff"))) {
2556 reply("NSMSG_ALLOWAUTH_STAFF", hi
->handle
);
2559 dict_insert(nickserv_allow_auth_dict
, target
->nick
, hi
);
2560 reply("NSMSG_AUTH_ALLOWED", target
->nick
, hi
->handle
);
2561 send_message(target
, nickserv
, "NSMSG_AUTH_ALLOWED_MSG", hi
->handle
, hi
->handle
);
2562 if (nickserv_conf
.email_enabled
)
2563 send_message(target
, nickserv
, "NSMSG_AUTH_ALLOWED_EMAIL");
2565 if (dict_remove(nickserv_allow_auth_dict
, target
->nick
))
2566 reply("NSMSG_AUTH_NORMAL_ONLY", target
->nick
);
2568 reply("NSMSG_AUTH_UNSPECIAL", target
->nick
);
2570 for (n
=0; n
<allowauth_func_used
; n
++)
2571 allowauth_func_list
[n
](user
, target
, hi
, allowauth_func_list_extra
[n
]);
2575 static NICKSERV_FUNC(cmd_authcookie
)
2577 struct handle_info
*hi
;
2579 NICKSERV_MIN_PARMS(2);
2580 if (user
->handle_info
) {
2581 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2584 if (IsStamped(user
)) {
2585 /* Unauthenticated users might still have been stamped
2586 previously and could therefore have a hidden host;
2587 do not allow them to authenticate to an account. */
2588 reply("NSMSG_STAMPED_AUTHCOOKIE");
2591 if (!(hi
= get_handle_info(argv
[1]))) {
2592 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2595 if (!hi
->email_addr
) {
2596 reply("MSG_SET_EMAIL_ADDR");
2599 nickserv_make_cookie(user
, hi
, ALLOWAUTH
, NULL
, 0);
2603 static NICKSERV_FUNC(cmd_delcookie
)
2605 struct handle_info
*hi
;
2607 hi
= user
->handle_info
;
2609 reply("NSMSG_NO_COOKIE");
2612 switch (hi
->cookie
->type
) {
2615 reply("NSMSG_MUST_TIME_OUT");
2618 nickserv_eat_cookie(hi
->cookie
);
2619 reply("NSMSG_ATE_COOKIE");
2625 static NICKSERV_FUNC(cmd_odelcookie
)
2627 struct handle_info
*hi
;
2629 NICKSERV_MIN_PARMS(2);
2631 if (!(hi
= get_victim_oper(user
, argv
[1])))
2635 reply("NSMSG_NO_COOKIE_FOREIGN", hi
->handle
);
2639 switch (hi
->cookie
->type
) {
2641 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2643 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2645 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2646 /* Falied to update password in ldap, but still
2647 * updated it here.. what should we do? */
2648 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2653 if (nickserv_conf
.sync_log
)
2654 SyncLog("ACCOUNTACC %s", hi
->handle
);
2656 case PASSWORD_CHANGE
:
2663 reply("NSMSG_BAD_COOKIE_TYPE", hi
->cookie
->type
);
2664 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d for account %s.", hi
->cookie
->type
, hi
->handle
);
2668 nickserv_eat_cookie(hi
->cookie
);
2669 reply("NSMSG_ATE_FOREIGN_COOKIE", hi
->handle
);
2674 static NICKSERV_FUNC(cmd_resetpass
)
2676 struct handle_info
*hi
;
2677 char crypted
[MD5_CRYPT_LENGTH
];
2680 NICKSERV_MIN_PARMS(3);
2681 if(argc
>= 4 && !strcmp(argv
[3], "WEBLINK"))
2685 if (user
->handle_info
) {
2686 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2689 if (IsStamped(user
)) {
2690 /* Unauthenticated users might still have been stamped
2691 previously and could therefore have a hidden host;
2692 do not allow them to activate an account. */
2693 reply("NSMSG_STAMPED_RESETPASS");
2696 if (!(hi
= get_handle_info(argv
[1]))) {
2697 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2700 if (!hi
->email_addr
) {
2701 reply("MSG_SET_EMAIL_ADDR");
2704 cryptpass(argv
[2], crypted
);
2706 nickserv_make_cookie(user
, hi
, PASSWORD_CHANGE
, crypted
, weblink
);
2710 static NICKSERV_FUNC(cmd_cookie
)
2712 struct handle_info
*hi
;
2715 if ((argc
== 2) && (hi
= user
->handle_info
) && hi
->cookie
&& (hi
->cookie
->type
== EMAIL_CHANGE
)) {
2718 NICKSERV_MIN_PARMS(3);
2719 if (!(hi
= get_handle_info(argv
[1]))) {
2720 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2726 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2727 reply("NSMSG_HANDLE_SUSPENDED");
2732 reply("NSMSG_NO_COOKIE");
2736 /* Check validity of operation before comparing cookie to
2737 * prohibit guessing by authed users. */
2738 if (user
->handle_info
2739 && (hi
->cookie
->type
!= EMAIL_CHANGE
)
2740 && (hi
->cookie
->type
!= PASSWORD_CHANGE
)) {
2741 reply("NSMSG_CANNOT_COOKIE");
2745 if (strcmp(cookie
, hi
->cookie
->cookie
)) {
2746 reply("NSMSG_BAD_COOKIE");
2750 switch (hi
->cookie
->type
) {
2753 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2755 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2756 /* Falied to update email in ldap, but still
2757 * updated it here.. what should we do? */
2758 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2763 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2764 set_user_handle_info(user
, hi
, 1);
2765 reply("NSMSG_HANDLE_ACTIVATED");
2766 if (nickserv_conf
.sync_log
)
2767 SyncLog("ACCOUNTACC %s", hi
->handle
);
2769 case PASSWORD_CHANGE
:
2771 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2773 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2774 /* Falied to update email in ldap, but still
2775 * updated it here.. what should we do? */
2776 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2781 set_user_handle_info(user
, hi
, 1);
2782 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2783 reply("NSMSG_PASSWORD_CHANGED");
2784 if (nickserv_conf
.sync_log
)
2785 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
2789 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2791 if((rc
= ldap_do_modify(hi
->handle
, NULL
, hi
->cookie
->data
)) != LDAP_SUCCESS
) {
2792 /* Falied to update email in ldap, but still
2793 * updated it here.. what should we do? */
2794 reply("NSMSG_LDAP_FAIL_SEND_EMAIL", ldap_err2string(rc
));
2799 if (!hi
->email_addr
&& nickserv_conf
.sync_log
) {
2801 * This should only happen if an OREGISTER was sent. Require
2802 * email must be enabled! - SiRVulcaN
2804 if (nickserv_conf
.sync_log
)
2805 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, hi
->cookie
->data
, user
->info
);
2808 nickserv_set_email_addr(hi
, hi
->cookie
->data
);
2809 reply("NSMSG_EMAIL_CHANGED");
2810 if (nickserv_conf
.sync_log
)
2811 SyncLog("EMAILCHANGE %s %s", hi
->handle
, hi
->cookie
->data
);
2814 char *mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2815 set_user_handle_info(user
, hi
, 1);
2816 nickserv_addmask(user
, hi
, mask
);
2817 reply("NSMSG_AUTH_SUCCESS");
2822 reply("NSMSG_BAD_COOKIE_TYPE", hi
->cookie
->type
);
2823 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d for account %s.", hi
->cookie
->type
, hi
->handle
);
2827 nickserv_eat_cookie(hi
->cookie
);
2829 process_adduser_pending(user
);
2834 static NICKSERV_FUNC(cmd_oregnick
) {
2836 struct handle_info
*target
;
2837 struct nick_info
*ni
;
2839 NICKSERV_MIN_PARMS(3);
2840 if (!(target
= modcmd_get_handle_info(user
, argv
[1])))
2843 if (!is_registerable_nick(nick
)) {
2844 reply("NSMSG_BAD_NICK", nick
);
2847 ni
= dict_find(nickserv_nick_dict
, nick
, NULL
);
2849 reply("NSMSG_NICK_EXISTS", nick
);
2852 register_nick(nick
, target
);
2853 reply("NSMSG_OREGNICK_SUCCESS", nick
, target
->handle
);
2857 static NICKSERV_FUNC(cmd_regnick
) {
2859 struct nick_info
*ni
;
2861 if (!is_registerable_nick(user
->nick
)) {
2862 reply("NSMSG_BAD_NICK", user
->nick
);
2865 /* count their nicks, see if it's too many */
2866 for (n
=0,ni
=user
->handle_info
->nicks
; ni
; n
++,ni
=ni
->next
) ;
2867 if (n
>= nickserv_conf
.nicks_per_handle
) {
2868 reply("NSMSG_TOO_MANY_NICKS");
2871 ni
= dict_find(nickserv_nick_dict
, user
->nick
, NULL
);
2873 reply("NSMSG_NICK_EXISTS", user
->nick
);
2876 register_nick(user
->nick
, user
->handle_info
);
2877 reply("NSMSG_REGNICK_SUCCESS", user
->nick
);
2881 static NICKSERV_FUNC(cmd_pass
)
2883 struct handle_info
*hi
;
2884 char *old_pass
, *new_pass
;
2885 char crypted
[MD5_CRYPT_LENGTH
+1];
2890 NICKSERV_MIN_PARMS(3);
2891 hi
= user
->handle_info
;
2895 if (!is_secure_password(hi
->handle
, new_pass
, user
)) return 0;
2898 if(nickserv_conf
.ldap_enable
) {
2899 ldap_result
= ldap_check_auth(hi
->handle
, old_pass
);
2900 if(ldap_result
!= LDAP_SUCCESS
) {
2901 if(ldap_result
== LDAP_INVALID_CREDENTIALS
)
2902 reply("NSMSG_PASSWORD_INVALID");
2904 reply("NSMSG_LDAP_FAIL", ldap_err2string(ldap_result
));
2909 if (!checkpass(old_pass
, hi
->passwd
)) {
2910 argv
[1] = "BADPASS";
2911 reply("NSMSG_PASSWORD_INVALID");
2914 cryptpass(new_pass
, crypted
);
2916 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2918 if((rc
= ldap_do_modify(hi
->handle
, crypted
, NULL
)) != LDAP_SUCCESS
) {
2919 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2924 //cryptpass(new_pass, hi->passwd);
2925 strcpy(hi
->passwd
, crypted
);
2926 if (nickserv_conf
.sync_log
)
2927 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
2929 reply("NSMSG_PASS_SUCCESS");
2934 nickserv_addmask(struct userNode
*user
, struct handle_info
*hi
, const char *mask
)
2937 char *new_mask
= canonicalize_hostmask(strdup(mask
));
2938 for (i
=0; i
<hi
->masks
->used
; i
++) {
2939 if (!irccasecmp(new_mask
, hi
->masks
->list
[i
])) {
2940 send_message(user
, nickserv
, "NSMSG_ADDMASK_ALREADY", new_mask
);
2945 string_list_append(hi
->masks
, new_mask
);
2946 send_message(user
, nickserv
, "NSMSG_ADDMASK_SUCCESS", new_mask
);
2950 static NICKSERV_FUNC(cmd_addmask
)
2953 char *mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2954 int res
= nickserv_addmask(user
, user
->handle_info
, mask
);
2958 if (!is_gline(argv
[1])) {
2959 reply("NSMSG_MASK_INVALID", argv
[1]);
2962 return nickserv_addmask(user
, user
->handle_info
, argv
[1]);
2966 static NICKSERV_FUNC(cmd_oaddmask
)
2968 struct handle_info
*hi
;
2970 NICKSERV_MIN_PARMS(3);
2971 if (!(hi
= get_victim_oper(user
, argv
[1])))
2973 return nickserv_addmask(user
, hi
, argv
[2]);
2977 nickserv_delmask(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, const char *del_mask
, int force
)
2980 for (i
=0; i
<hi
->masks
->used
; i
++) {
2981 if (!strcmp(del_mask
, hi
->masks
->list
[i
])) {
2982 char *old_mask
= hi
->masks
->list
[i
];
2983 if (hi
->masks
->used
== 1 && !force
) {
2984 reply("NSMSG_DELMASK_NOTLAST");
2987 hi
->masks
->list
[i
] = hi
->masks
->list
[--hi
->masks
->used
];
2988 reply("NSMSG_DELMASK_SUCCESS", old_mask
);
2993 reply("NSMSG_DELMASK_NOT_FOUND");
2997 static NICKSERV_FUNC(cmd_delmask
)
2999 NICKSERV_MIN_PARMS(2);
3000 return nickserv_delmask(cmd
, user
, user
->handle_info
, argv
[1], 0);
3003 static NICKSERV_FUNC(cmd_odelmask
)
3005 struct handle_info
*hi
;
3006 NICKSERV_MIN_PARMS(3);
3007 if (!(hi
= get_victim_oper(user
, argv
[1])))
3009 return nickserv_delmask(cmd
, user
, hi
, argv
[2], 1);
3013 nickserv_addsslfp(struct userNode
*user
, struct handle_info
*hi
, const char *sslfp
)
3016 char *new_sslfp
= strdup(sslfp
);
3017 for (i
=0; i
<hi
->sslfps
->used
; i
++) {
3018 if (!irccasecmp(new_sslfp
, hi
->sslfps
->list
[i
])) {
3019 send_message(user
, nickserv
, "NSMSG_ADDSSLFP_ALREADY", new_sslfp
);
3024 string_list_append(hi
->sslfps
, new_sslfp
);
3025 send_message(user
, nickserv
, "NSMSG_ADDSSLFP_SUCCESS", new_sslfp
);
3029 static NICKSERV_FUNC(cmd_addsslfp
)
3031 NICKSERV_MIN_PARMS((user
->sslfp
? 1 : 2));
3032 if ((argc
< 2) && (user
->sslfp
)) {
3033 int res
= nickserv_addsslfp(user
, user
->handle_info
, user
->sslfp
);
3036 return nickserv_addsslfp(user
, user
->handle_info
, argv
[1]);
3040 static NICKSERV_FUNC(cmd_oaddsslfp
)
3042 struct handle_info
*hi
;
3044 NICKSERV_MIN_PARMS(3);
3045 if (!(hi
= get_victim_oper(user
, argv
[1])))
3047 return nickserv_addsslfp(user
, hi
, argv
[2]);
3051 nickserv_delsslfp(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, const char *del_sslfp
)
3054 for (i
=0; i
<hi
->sslfps
->used
; i
++) {
3055 if (!irccasecmp(del_sslfp
, hi
->sslfps
->list
[i
])) {
3056 char *old_sslfp
= hi
->sslfps
->list
[i
];
3057 hi
->sslfps
->list
[i
] = hi
->sslfps
->list
[--hi
->sslfps
->used
];
3058 reply("NSMSG_DELSSLFP_SUCCESS", old_sslfp
);
3063 reply("NSMSG_DELSSLFP_NOT_FOUND");
3067 static NICKSERV_FUNC(cmd_delsslfp
)
3069 NICKSERV_MIN_PARMS((user
->sslfp
? 1 : 2));
3070 if ((argc
< 2) && (user
->sslfp
)) {
3071 return nickserv_delsslfp(cmd
, user
, user
->handle_info
, user
->sslfp
);
3073 return nickserv_delsslfp(cmd
, user
, user
->handle_info
, argv
[1]);
3077 static NICKSERV_FUNC(cmd_odelsslfp
)
3079 struct handle_info
*hi
;
3080 NICKSERV_MIN_PARMS(3);
3081 if (!(hi
= get_victim_oper(user
, argv
[1])))
3083 return nickserv_delsslfp(cmd
, user
, hi
, argv
[2]);
3087 nickserv_modify_handle_flags(struct userNode
*user
, struct userNode
*bot
, const char *str
, unsigned long *padded
, unsigned long *premoved
) {
3088 unsigned int nn
, add
= 1, pos
;
3089 unsigned long added
, removed
, flag
;
3091 for (added
=removed
=nn
=0; str
[nn
]; nn
++) {
3093 case '+': add
= 1; break;
3094 case '-': add
= 0; break;
3096 if (!(pos
= handle_inverse_flags
[(unsigned char)str
[nn
]])) {
3097 send_message(user
, bot
, "NSMSG_INVALID_FLAG", str
[nn
]);
3100 if (user
&& (user
->handle_info
->opserv_level
< flag_access_levels
[pos
-1])) {
3101 /* cheesy avoidance of looking up the flag name.. */
3102 send_message(user
, bot
, "NSMSG_FLAG_PRIVILEGED", str
[nn
]);
3105 flag
= 1 << (pos
- 1);
3107 added
|= flag
, removed
&= ~flag
;
3109 removed
|= flag
, added
&= ~flag
;
3114 *premoved
= removed
;
3119 nickserv_apply_flags(struct userNode
*user
, struct handle_info
*hi
, const char *flags
)
3121 unsigned long before
, after
, added
, removed
;
3122 struct userNode
*uNode
;
3124 before
= hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
);
3125 if (!nickserv_modify_handle_flags(user
, nickserv
, flags
, &added
, &removed
))
3127 hi
->flags
= (hi
->flags
| added
) & ~removed
;
3128 after
= hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
);
3130 /* Strip helping flag if they're only a support helper and not
3131 * currently in #support. */
3132 if (HANDLE_FLAGGED(hi
, HELPING
) && (after
== HI_FLAG_SUPPORT_HELPER
)) {
3133 struct channelList
*schannels
;
3135 schannels
= chanserv_support_channels();
3136 for (ii
= 0; ii
< schannels
->used
; ++ii
)
3137 if (find_handle_in_channel(schannels
->list
[ii
], hi
, NULL
))
3139 if (ii
== schannels
->used
)
3140 HANDLE_CLEAR_FLAG(hi
, HELPING
);
3143 if (after
&& !before
) {
3144 /* Add user to current helper list. */
3145 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
3146 userList_append(&curr_helpers
, uNode
);
3147 } else if (!after
&& before
) {
3148 /* Remove user from current helper list. */
3149 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
3150 userList_remove(&curr_helpers
, uNode
);
3157 set_list(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, int override
)
3161 char *set_display
[] = {
3162 "INFO", "WIDTH", "TABLEWIDTH", "COLOR", "PRIVMSG", "STYLE",
3163 "EMAIL", "ANNOUNCEMENTS", "AUTOHIDE", "MAXLOGINS", "LANGUAGE",
3164 "FAKEHOST", "TITLE", "EPITHET", "ADVANCED"
3167 reply("NSMSG_SETTING_LIST");
3168 reply("NSMSG_SETTING_LIST_HEADER");
3170 /* Do this so options are presented in a consistent order. */
3171 for (i
= 0; i
< ArrayLength(set_display
); ++i
)
3172 if ((opt
= dict_find(nickserv_opt_dict
, set_display
[i
], NULL
)))
3173 opt(cmd
, user
, hi
, override
, 0, 0, NULL
);
3174 reply("NSMSG_SETTING_LIST_END");
3177 static NICKSERV_FUNC(cmd_set
)
3179 struct handle_info
*hi
;
3182 hi
= user
->handle_info
;
3184 set_list(cmd
, user
, hi
, 0);
3187 if (!(opt
= dict_find(nickserv_opt_dict
, argv
[1], NULL
))) {
3188 reply("NSMSG_INVALID_OPTION", argv
[1]);
3191 return opt(cmd
, user
, hi
, 0, 0, argc
-1, argv
+1);
3194 static NICKSERV_FUNC(cmd_oset
)
3196 struct handle_info
*hi
;
3199 NICKSERV_MIN_PARMS(2);
3201 if (!(hi
= get_victim_oper(user
, argv
[1])))
3205 set_list(cmd
, user
, hi
, 0);
3209 if (!(opt
= dict_find(nickserv_opt_dict
, argv
[2], NULL
))) {
3210 reply("NSMSG_INVALID_OPTION", argv
[2]);
3214 return opt(cmd
, user
, hi
, 1, 0, argc
-2, argv
+2);
3217 static OPTION_FUNC(opt_info
)
3221 if ((argv
[1][0] == '*') && (argv
[1][1] == 0)) {
3223 hi
->infoline
= NULL
;
3225 hi
->infoline
= strdup(unsplit_string(argv
+1, argc
-1, NULL
));
3229 info
= hi
->infoline
? hi
->infoline
: user_find_message(user
, "MSG_NONE");
3231 reply("NSMSG_SET_INFO", info
);
3235 static OPTION_FUNC(opt_width
)
3238 hi
->screen_width
= strtoul(argv
[1], NULL
, 0);
3240 if ((hi
->screen_width
> 0) && (hi
->screen_width
< MIN_LINE_SIZE
))
3241 hi
->screen_width
= MIN_LINE_SIZE
;
3242 else if (hi
->screen_width
> MAX_LINE_SIZE
)
3243 hi
->screen_width
= MAX_LINE_SIZE
;
3246 reply("NSMSG_SET_WIDTH", hi
->screen_width
);
3250 static OPTION_FUNC(opt_tablewidth
)
3253 hi
->table_width
= strtoul(argv
[1], NULL
, 0);
3255 if ((hi
->table_width
> 0) && (hi
->table_width
< MIN_LINE_SIZE
))
3256 hi
->table_width
= MIN_LINE_SIZE
;
3257 else if (hi
->screen_width
> MAX_LINE_SIZE
)
3258 hi
->table_width
= MAX_LINE_SIZE
;
3261 reply("NSMSG_SET_TABLEWIDTH", hi
->table_width
);
3265 static OPTION_FUNC(opt_color
)
3268 if (enabled_string(argv
[1]))
3269 HANDLE_SET_FLAG(hi
, MIRC_COLOR
);
3270 else if (disabled_string(argv
[1]))
3271 HANDLE_CLEAR_FLAG(hi
, MIRC_COLOR
);
3274 reply("MSG_INVALID_BINARY", argv
[1]);
3280 reply("NSMSG_SET_COLOR", user_find_message(user
, HANDLE_FLAGGED(hi
, MIRC_COLOR
) ? "MSG_ON" : "MSG_OFF"));
3284 static OPTION_FUNC(opt_privmsg
)
3287 if (enabled_string(argv
[1]))
3288 HANDLE_SET_FLAG(hi
, USE_PRIVMSG
);
3289 else if (disabled_string(argv
[1]))
3290 HANDLE_CLEAR_FLAG(hi
, USE_PRIVMSG
);
3293 reply("MSG_INVALID_BINARY", argv
[1]);
3299 reply("NSMSG_SET_PRIVMSG", user_find_message(user
, HANDLE_FLAGGED(hi
, USE_PRIVMSG
) ? "MSG_ON" : "MSG_OFF"));
3303 static OPTION_FUNC(opt_autohide
)
3306 if (enabled_string(argv
[1]))
3307 HANDLE_SET_FLAG(hi
, AUTOHIDE
);
3308 else if (disabled_string(argv
[1]))
3309 HANDLE_CLEAR_FLAG(hi
, AUTOHIDE
);
3312 reply("MSG_INVALID_BINARY", argv
[1]);
3318 reply("NSMSG_SET_AUTOHIDE", user_find_message(user
, HANDLE_FLAGGED(hi
, AUTOHIDE
) ? "MSG_ON" : "MSG_OFF"));
3322 static OPTION_FUNC(opt_style
)
3327 if (!irccasecmp(argv
[1], "Clean"))
3328 hi
->userlist_style
= HI_STYLE_CLEAN
;
3329 else if (!irccasecmp(argv
[1], "Advanced"))
3330 hi
->userlist_style
= HI_STYLE_ADVANCED
;
3331 else if (!irccasecmp(argv
[1], "Classic"))
3332 hi
->userlist_style
= HI_STYLE_CLASSIC
;
3333 else /* Default to normal */
3334 hi
->userlist_style
= HI_STYLE_NORMAL
;
3335 } /* TODO: give error if unknow style is chosen */
3337 switch (hi
->userlist_style
) {
3338 case HI_STYLE_ADVANCED
:
3341 case HI_STYLE_CLASSIC
:
3344 case HI_STYLE_CLEAN
:
3347 case HI_STYLE_NORMAL
:
3353 reply("NSMSG_SET_STYLE", style
);
3357 static OPTION_FUNC(opt_announcements
)
3362 if (enabled_string(argv
[1]))
3363 hi
->announcements
= 'y';
3364 else if (disabled_string(argv
[1]))
3365 hi
->announcements
= 'n';
3366 else if (!strcmp(argv
[1], "?") || !irccasecmp(argv
[1], "default"))
3367 hi
->announcements
= '?';
3370 reply("NSMSG_INVALID_ANNOUNCE", argv
[1]);
3375 switch (hi
->announcements
) {
3376 case 'y': choice
= user_find_message(user
, "MSG_ON"); break;
3377 case 'n': choice
= user_find_message(user
, "MSG_OFF"); break;
3378 case '?': choice
= "default"; break;
3379 default: choice
= "unknown"; break;
3382 reply("NSMSG_SET_ANNOUNCEMENTS", choice
);
3386 static OPTION_FUNC(opt_password
)
3388 char crypted
[MD5_CRYPT_LENGTH
+1];
3394 reply("NSMSG_USE_CMD_PASS");
3398 cryptpass(argv
[1], crypted
);
3400 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
3402 if((rc
= ldap_do_modify(hi
->handle
, crypted
, NULL
)) != LDAP_SUCCESS
) {
3404 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3409 strcpy(hi
->passwd
, crypted
);
3410 if (nickserv_conf
.sync_log
)
3411 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
3414 reply("NSMSG_SET_PASSWORD", "***");
3418 static OPTION_FUNC(opt_flags
)
3421 unsigned int ii
, flen
;
3425 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3430 nickserv_apply_flags(user
, hi
, argv
[1]);
3432 for (ii
= flen
= 0; handle_flags
[ii
]; ii
++)
3433 if (hi
->flags
& (1 << ii
))
3434 flags
[flen
++] = handle_flags
[ii
];
3438 reply("NSMSG_SET_FLAGS", flags
);
3440 reply("NSMSG_SET_FLAGS", user_find_message(user
, "MSG_NONE"));
3445 static OPTION_FUNC(opt_email
)
3449 if (!valid_email(argv
[1])) {
3451 reply("NSMSG_BAD_EMAIL_ADDR");
3454 if ((str
= mail_prohibited_address(argv
[1]))) {
3456 reply("NSMSG_EMAIL_PROHIBITED", argv
[1], str
);
3459 if (hi
->email_addr
&& !irccasecmp(hi
->email_addr
, argv
[1])) {
3461 reply("NSMSG_EMAIL_SAME");
3462 } else if (!override
)
3463 nickserv_make_cookie(user
, hi
, EMAIL_CHANGE
, argv
[1], 0);
3466 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
3468 if((rc
= ldap_do_modify(hi
->handle
, NULL
, argv
[1])) != LDAP_SUCCESS
) {
3470 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3475 nickserv_set_email_addr(hi
, argv
[1]);
3477 nickserv_eat_cookie(hi
->cookie
);
3479 reply("NSMSG_SET_EMAIL", visible_email_addr(user
, hi
));
3483 reply("NSMSG_SET_EMAIL", visible_email_addr(user
, hi
));
3488 static OPTION_FUNC(opt_maxlogins
)
3490 unsigned char maxlogins
;
3492 maxlogins
= strtoul(argv
[1], NULL
, 0);
3493 if ((maxlogins
> nickserv_conf
.hard_maxlogins
) && !override
) {
3495 reply("NSMSG_BAD_MAX_LOGINS", nickserv_conf
.hard_maxlogins
);
3498 hi
->maxlogins
= maxlogins
;
3500 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
3502 reply("NSMSG_SET_MAXLOGINS", maxlogins
);
3506 static OPTION_FUNC(opt_advanced
)
3509 if (enabled_string(argv
[1]))
3510 HANDLE_SET_FLAG(hi
, ADVANCED
);
3511 else if (disabled_string(argv
[1]))
3512 HANDLE_CLEAR_FLAG(hi
, ADVANCED
);
3515 reply("MSG_INVALID_BINARY", argv
[1]);
3521 reply("NSMSG_SET_ADVANCED", user_find_message(user
, HANDLE_FLAGGED(hi
, ADVANCED
) ? "MSG_ON" : "MSG_OFF"));
3525 static OPTION_FUNC(opt_language
)
3527 struct language
*lang
;
3529 lang
= language_find(argv
[1]);
3530 if (irccasecmp(lang
->name
, argv
[1])) {
3532 reply("NSMSG_LANGUAGE_NOT_FOUND", argv
[1], lang
->name
);
3534 hi
->language
= lang
;
3537 reply("NSMSG_SET_LANGUAGE", hi
->language
->name
);
3541 static OPTION_FUNC(opt_karma
)
3545 send_message(user
, nickserv
, "MSG_SETTING_PRIVILEGED", argv
[0]);
3550 if (argv
[1][0] == '+' && isdigit(argv
[1][1])) {
3551 hi
->karma
+= strtoul(argv
[1] + 1, NULL
, 10);
3552 } else if (argv
[1][0] == '-' && isdigit(argv
[1][1])) {
3553 hi
->karma
-= strtoul(argv
[1] + 1, NULL
, 10);
3556 send_message(user
, nickserv
, "NSMSG_INVALID_KARMA", argv
[1]);
3561 send_message(user
, nickserv
, "NSMSG_SET_KARMA", hi
->karma
);
3565 /* Called from opserv from cmd_access */
3567 oper_try_set_access(struct userNode
*user
, struct userNode
*bot
, struct handle_info
*target
, unsigned int new_level
) {
3568 if (!oper_has_access(user
, bot
, nickserv_conf
.modoper_level
, 0))
3570 if ((user
->handle_info
->opserv_level
< target
->opserv_level
)
3571 || ((user
->handle_info
->opserv_level
== target
->opserv_level
)
3572 && (user
->handle_info
->opserv_level
< 1000))) {
3573 send_message(user
, bot
, "MSG_USER_OUTRANKED", target
->handle
);
3576 if ((user
->handle_info
->opserv_level
< new_level
)
3577 || ((user
->handle_info
->opserv_level
== new_level
)
3578 && (user
->handle_info
->opserv_level
< 1000))) {
3579 send_message(user
, bot
, "NSMSG_OPSERV_LEVEL_BAD");
3582 if (user
->handle_info
== target
) {
3583 send_message(user
, bot
, "MSG_STUPID_ACCESS_CHANGE");
3587 if(nickserv_conf
.ldap_enable
&& *(nickserv_conf
.ldap_oper_group_dn
) && *(nickserv_conf
.ldap_admin_dn
)) {
3589 if(new_level
> nickserv_conf
.ldap_oper_group_level
)
3590 rc
= ldap_add2group(target
->handle
, nickserv_conf
.ldap_oper_group_dn
);
3592 rc
= ldap_delfromgroup(target
->handle
, nickserv_conf
.ldap_oper_group_dn
);
3593 if(rc
!= LDAP_SUCCESS
&& rc
!= LDAP_TYPE_OR_VALUE_EXISTS
&& rc
!= LDAP_NO_SUCH_ATTRIBUTE
) {
3594 send_message(user
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3598 if(nickserv_conf
.ldap_enable
&& *(nickserv_conf
.ldap_field_oslevel
) && *(nickserv_conf
.ldap_admin_dn
)) {
3600 if((rc
= ldap_do_oslevel(target
->handle
, new_level
, target
->opserv_level
)) != LDAP_SUCCESS
) {
3601 send_message(user
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3606 if (target
->opserv_level
== new_level
)
3608 log_module(NS_LOG
, LOG_INFO
, "Account %s setting oper level for account %s to %d (from %d).",
3609 user
->handle_info
->handle
, target
->handle
, new_level
, target
->opserv_level
);
3610 target
->opserv_level
= new_level
;
3614 static OPTION_FUNC(opt_level
)
3620 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3624 res
= (argc
> 1) ? oper_try_set_access(user
, nickserv
, hi
, strtoul(argv
[1], NULL
, 0)) : 0;
3626 reply("NSMSG_SET_LEVEL", hi
->opserv_level
);
3630 static OPTION_FUNC(opt_epithet
)
3632 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_epithet_level
, 0)) {
3634 struct userNode
*target
, *next_un
;
3638 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3642 epithet
= unsplit_string(argv
+1, argc
-1, NULL
);
3646 if ((epithet
[0] == '*') && !epithet
[1])
3649 hi
->epithet
= strdup(epithet
);
3651 for (target
= hi
->users
; target
; target
= next_un
) {
3652 irc_swhois(nickserv
, target
, hi
->epithet
);
3654 next_un
= target
->next_authed
;
3660 reply("NSMSG_SET_EPITHET", hi
->epithet
);
3662 reply("NSMSG_SET_EPITHET", user_find_message(user
, "MSG_NONE"));
3667 static OPTION_FUNC(opt_title
)
3670 const char *none
= NULL
;
3673 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_title_level
, 0)) {
3676 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3681 if(!strcmp(title
, "*")) {
3683 hi
->fakehost
= NULL
;
3686 if (strchr(title
, '.')) {
3688 reply("NSMSG_TITLE_INVALID");
3691 /* Alphanumeric titles only. */
3692 for(sptr
= title
; *sptr
; sptr
++) {
3693 if(!isalnum(*sptr
) && *sptr
!= '-') {
3695 reply("NSMSG_TITLE_INVALID");
3699 if ((strlen(user
->handle_info
->handle
) + strlen(title
) +
3700 strlen(nickserv_conf
.titlehost_suffix
) + 2) > HOSTLEN
) {
3702 reply("NSMSG_TITLE_TRUNCATED");
3706 hi
->fakehost
= malloc(strlen(title
)+2);
3707 hi
->fakehost
[0] = '.';
3708 strcpy(hi
->fakehost
+1, title
);
3711 } else if (hi
->fakehost
&& (hi
->fakehost
[0] == '.'))
3712 title
= hi
->fakehost
+ 1;
3714 /* If theres no title set then the default title will therefore
3715 be the first part of hidden_host in x3.conf, so for
3716 consistency with opt_fakehost we will print this here.
3717 This isnt actually used in P10, its just handled to keep from crashing... */
3718 char *hs
, *hidden_suffix
, *rest
;
3720 hs
= conf_get_data("server/hidden_host", RECDB_QSTRING
);
3721 hidden_suffix
= strdup(hs
);
3723 /* Yes we do this twice */
3724 if((rest
= strchr(hidden_suffix
, '.')))
3727 title
= hidden_suffix
;
3731 /* A lame default if someone configured hidden_host to something lame */
3732 title
= strdup("users");
3733 free(hidden_suffix
);
3739 none
= user_find_message(user
, "MSG_NONE");
3741 send_message(user
, nickserv
, "NSMSG_SET_TITLE", title
? title
: none
);
3746 check_vhost(char *vhost
, struct userNode
*user
, struct svccmd
*cmd
)
3750 // check for a dot in the vhost
3751 if(strchr(vhost
, '.') == NULL
) {
3752 reply("NSMSG_NOT_VALID_FAKEHOST_DOT", vhost
);
3756 // check for a @ in the vhost
3757 if(strchr(vhost
, '@') != NULL
) {
3758 reply("NSMSG_NOT_VALID_FAKEHOST_AT", vhost
);
3762 // check for denied words, inspired by monk at paki.sex
3763 for(y
= 0; y
< nickserv_conf
.denied_fakehost_words
->used
; y
++) {
3764 if(strstr(vhost
, nickserv_conf
.denied_fakehost_words
->list
[y
]) != NULL
) {
3765 reply("NSMSG_DENIED_FAKEHOST_WORD", vhost
, nickserv_conf
.denied_fakehost_words
->list
[y
]);
3770 // check for ircu's HOSTLEN length.
3771 if(strlen(vhost
) >= HOSTLEN
) {
3772 reply("NSMSG_NOT_VALID_FAKEHOST_LEN", vhost
);
3776 /* This can be handled by the regex now if desired.
3777 if (vhost[strspn(vhost, "0123456789.")]) {
3778 hostname = vhost + strlen(vhost);
3779 for (depth = 1; depth && (hostname > vhost); depth--) {
3781 while ((hostname > vhost) && (*hostname != '.')) hostname--;
3784 if (*hostname == '.') hostname++; * advance past last dot we saw *
3785 if(strlen(hostname) > 4) {
3786 reply("NSMSG_NOT_VALID_FAKEHOST_TLD_LEN", vhost);
3791 /* test either regex or as valid handle */
3792 if (nickserv_conf
.valid_fakehost_regex_set
) {
3793 int err
= regexec(&nickserv_conf
.valid_fakehost_regex
, vhost
, 0, 0, 0);
3796 buff
[regerror(err
, &nickserv_conf
.valid_fakehost_regex
, buff
, sizeof(buff
))] = 0;
3797 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
3799 if(err
== REG_NOMATCH
) {
3800 reply("NSMSG_NOT_VALID_FAKEHOST_REGEX", vhost
);
3809 static OPTION_FUNC(opt_fakehost
)
3813 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_fakehost_level
, 0)) {
3816 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3821 if ((strlen(fake
) > HOSTLEN
) || (fake
[0] == '.')) {
3823 reply("NSMSG_FAKEHOST_INVALID", HOSTLEN
);
3826 if (!strcmp(fake
, "*")) {
3829 hi
->fakehost
= NULL
;
3832 else if (!check_vhost(argv
[1], user
, cmd
)) {
3833 /* check_vhost takes care of error reply */
3839 hi
->fakehost
= strdup(fake
);
3842 fake
= hi
->fakehost
;
3844 fake
= generate_fakehost(hi
);
3846 /* Tell them we set the host */
3848 fake
= user_find_message(user
, "MSG_NONE");
3850 reply("NSMSG_SET_FAKEHOST", fake
);
3854 static OPTION_FUNC(opt_note
)
3858 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3863 char *text
= unsplit_string(argv
+ 1, argc
- 1, NULL
);
3868 if ((text
[0] == '*') && !text
[1])
3871 if (!(hi
->note
= nickserv_add_note(user
->handle_info
->handle
, now
, text
)))
3877 reply("NSMSG_SET_NOTE", hi
->note
? hi
->note
->note
: user_find_message(user
, "MSG_NONE"));
3881 static NICKSERV_FUNC(cmd_reclaim
)
3883 struct handle_info
*hi
;
3884 struct nick_info
*ni
;
3885 struct userNode
*victim
;
3887 NICKSERV_MIN_PARMS(2);
3888 hi
= user
->handle_info
;
3889 ni
= dict_find(nickserv_nick_dict
, argv
[1], 0);
3891 reply("NSMSG_UNKNOWN_NICK", argv
[1]);
3894 if (ni
->owner
!= user
->handle_info
) {
3895 reply("NSMSG_NOT_YOUR_NICK", ni
->nick
);
3898 victim
= GetUserH(ni
->nick
);
3900 reply("MSG_NICK_UNKNOWN", ni
->nick
);
3903 if (victim
== user
) {
3904 reply("NSMSG_NICK_USER_YOU");
3907 nickserv_reclaim(victim
, ni
, nickserv_conf
.reclaim_action
);
3908 switch (nickserv_conf
.reclaim_action
) {
3909 case RECLAIM_NONE
: reply("NSMSG_RECLAIMED_NONE"); break;
3910 case RECLAIM_WARN
: reply("NSMSG_RECLAIMED_WARN", victim
->nick
); break;
3911 case RECLAIM_SVSNICK
: reply("NSMSG_RECLAIMED_SVSNICK", victim
->nick
); break;
3912 case RECLAIM_KILL
: reply("NSMSG_RECLAIMED_KILL", victim
->nick
); break;
3917 static NICKSERV_FUNC(cmd_unregnick
)
3920 struct handle_info
*hi
;
3921 struct nick_info
*ni
;
3923 hi
= user
->handle_info
;
3924 nick
= (argc
< 2) ? user
->nick
: (const char*)argv
[1];
3925 ni
= dict_find(nickserv_nick_dict
, nick
, NULL
);
3927 reply("NSMSG_UNKNOWN_NICK", nick
);
3930 if (hi
!= ni
->owner
) {
3931 reply("NSMSG_NOT_YOUR_NICK", nick
);
3934 reply("NSMSG_UNREGNICK_SUCCESS", ni
->nick
);
3939 static NICKSERV_FUNC(cmd_ounregnick
)
3941 struct nick_info
*ni
;
3943 NICKSERV_MIN_PARMS(2);
3944 if (!(ni
= get_nick_info(argv
[1]))) {
3945 reply("NSMSG_NICK_NOT_REGISTERED", argv
[1]);
3948 if (!oper_outranks(user
, ni
->owner
))
3950 reply("NSMSG_UNREGNICK_SUCCESS", ni
->nick
);
3955 static NICKSERV_FUNC(cmd_unregister
)
3957 struct handle_info
*hi
;
3960 NICKSERV_MIN_PARMS(2);
3961 hi
= user
->handle_info
;
3964 if (checkpass(passwd
, hi
->passwd
)) {
3965 if(nickserv_unregister_handle(hi
, user
, cmd
->parent
->bot
))
3970 log_module(NS_LOG
, LOG_INFO
, "Account '%s' tried to unregister with the wrong password.", hi
->handle
);
3971 reply("NSMSG_PASSWORD_INVALID");
3976 static NICKSERV_FUNC(cmd_ounregister
)
3978 struct handle_info
*hi
;
3979 char reason
[MAXLEN
];
3982 NICKSERV_MIN_PARMS(2);
3983 if (!(hi
= get_victim_oper(user
, argv
[1])))
3986 if (HANDLE_FLAGGED(hi
, NODELETE
)) {
3987 reply("NSMSG_UNREGISTER_NODELETE", hi
->handle
);
3991 force
= IsOper(user
) && (argc
> 2) && !irccasecmp(argv
[2], "force");
3993 ((hi
->flags
& nickserv_conf
.ounregister_flags
)
3995 || (hi
->last_quit_host
[0] && ((unsigned)(now
- hi
->lastseen
) < nickserv_conf
.ounregister_inactive
)))) {
3996 reply((IsOper(user
) ? "NSMSG_UNREGISTER_MUST_FORCE" : "NSMSG_UNREGISTER_CANNOT_FORCE"), hi
->handle
);
3999 snprintf(reason
, sizeof(reason
), "%s unregistered account %s.", user
->handle_info
->handle
, hi
->handle
);
4000 global_message(MESSAGE_RECIPIENT_STAFF
, reason
);
4001 if(nickserv_unregister_handle(hi
, user
, cmd
->parent
->bot
))
4007 static NICKSERV_FUNC(cmd_status
)
4009 if (nickserv_conf
.disable_nicks
) {
4010 reply("NSMSG_GLOBAL_STATS_NONICK",
4011 dict_size(nickserv_handle_dict
));
4013 if (user
->handle_info
) {
4015 struct nick_info
*ni
;
4016 for (ni
=user
->handle_info
->nicks
; ni
; ni
=ni
->next
) cnt
++;
4017 reply("NSMSG_HANDLE_STATS", cnt
);
4019 reply("NSMSG_HANDLE_NONE");
4021 reply("NSMSG_GLOBAL_STATS",
4022 dict_size(nickserv_handle_dict
),
4023 dict_size(nickserv_nick_dict
));
4028 static NICKSERV_FUNC(cmd_ghost
)
4030 struct userNode
*target
;
4031 char reason
[MAXLEN
];
4033 NICKSERV_MIN_PARMS(2);
4034 if (!(target
= GetUserH(argv
[1]))) {
4035 reply("MSG_NICK_UNKNOWN", argv
[1]);
4038 if (target
== user
) {
4039 reply("NSMSG_CANNOT_GHOST_SELF");
4042 if (!target
->handle_info
|| (target
->handle_info
!= user
->handle_info
)) {
4043 reply("NSMSG_CANNOT_GHOST_USER", target
->nick
);
4046 snprintf(reason
, sizeof(reason
), "Ghost kill on account %s (requested by %s).", target
->handle_info
->handle
, user
->nick
);
4047 DelUser(target
, nickserv
, 1, reason
);
4048 reply("NSMSG_GHOST_KILLED", argv
[1]);
4052 static NICKSERV_FUNC(cmd_vacation
)
4054 HANDLE_SET_FLAG(user
->handle_info
, FROZEN
);
4055 reply("NSMSG_ON_VACATION");
4060 nickserv_saxdb_write(struct saxdb_context
*ctx
) {
4062 struct handle_info
*hi
;
4065 for (it
= dict_first(nickserv_handle_dict
); it
; it
= iter_next(it
)) {
4067 saxdb_start_record(ctx
, iter_key(it
), 0);
4068 if (hi
->announcements
!= '?') {
4069 flags
[0] = hi
->announcements
;
4071 saxdb_write_string(ctx
, KEY_ANNOUNCEMENTS
, flags
);
4074 struct handle_cookie
*cookie
= hi
->cookie
;
4077 switch (cookie
->type
) {
4078 case ACTIVATION
: type
= KEY_ACTIVATION
; break;
4079 case PASSWORD_CHANGE
: type
= KEY_PASSWORD_CHANGE
; break;
4080 case EMAIL_CHANGE
: type
= KEY_EMAIL_CHANGE
; break;
4081 case ALLOWAUTH
: type
= KEY_ALLOWAUTH
; break;
4082 default: type
= NULL
; break;
4085 saxdb_start_record(ctx
, KEY_COOKIE
, 0);
4086 saxdb_write_string(ctx
, KEY_COOKIE_TYPE
, type
);
4087 saxdb_write_int(ctx
, KEY_COOKIE_EXPIRES
, cookie
->expires
);
4089 saxdb_write_string(ctx
, KEY_COOKIE_DATA
, cookie
->data
);
4090 saxdb_write_string(ctx
, KEY_COOKIE
, cookie
->cookie
);
4091 saxdb_end_record(ctx
);
4095 saxdb_write_string(ctx
, KEY_EMAIL_ADDR
, hi
->email_addr
);
4097 saxdb_write_string(ctx
, KEY_EPITHET
, hi
->epithet
);
4099 saxdb_start_record(ctx
, KEY_NOTE_NOTE
, 0);
4100 saxdb_write_string(ctx
, KEY_NOTE_SETTER
, hi
->note
->setter
);
4101 saxdb_write_int(ctx
, KEY_NOTE_DATE
, hi
->note
->date
);
4102 saxdb_write_string(ctx
, KEY_NOTE_NOTE
, hi
->note
->note
);
4103 saxdb_end_record(ctx
);
4107 saxdb_write_string(ctx
, KEY_FAKEHOST
, hi
->fakehost
);
4111 for (ii
=flen
=0; handle_flags
[ii
]; ++ii
)
4112 if (hi
->flags
& (1 << ii
))
4113 flags
[flen
++] = handle_flags
[ii
];
4115 saxdb_write_string(ctx
, KEY_FLAGS
, flags
);
4118 saxdb_write_string(ctx
, KEY_INFO
, hi
->infoline
);
4119 if (hi
->last_quit_host
[0])
4120 saxdb_write_string(ctx
, KEY_LAST_QUIT_HOST
, hi
->last_quit_host
);
4121 saxdb_write_int(ctx
, KEY_LAST_SEEN
, hi
->lastseen
);
4123 saxdb_write_sint(ctx
, KEY_KARMA
, hi
->karma
);
4124 if (hi
->masks
->used
)
4125 saxdb_write_string_list(ctx
, KEY_MASKS
, hi
->masks
);
4126 if (hi
->sslfps
->used
)
4127 saxdb_write_string_list(ctx
, KEY_SSLFPS
, hi
->sslfps
);
4128 if (hi
->ignores
->used
)
4129 saxdb_write_string_list(ctx
, KEY_IGNORES
, hi
->ignores
);
4131 saxdb_write_int(ctx
, KEY_MAXLOGINS
, hi
->maxlogins
);
4133 struct nick_info
*ni
;
4135 saxdb_start_record(ctx
, KEY_NICKS_EX
, 0);
4136 for (ni
= hi
->nicks
; ni
; ni
= ni
->next
) {
4137 saxdb_start_record(ctx
, ni
->nick
, 0);
4138 saxdb_write_int(ctx
, KEY_REGISTER_ON
, ni
->registered
);
4139 saxdb_write_int(ctx
, KEY_LAST_SEEN
, ni
->lastseen
);
4140 saxdb_end_record(ctx
);
4142 saxdb_end_record(ctx
);
4144 if (hi
->opserv_level
)
4145 saxdb_write_int(ctx
, KEY_OPSERV_LEVEL
, hi
->opserv_level
);
4146 if (hi
->language
!= lang_C
)
4147 saxdb_write_string(ctx
, KEY_LANGUAGE
, hi
->language
->name
);
4148 saxdb_write_string(ctx
, KEY_PASSWD
, hi
->passwd
);
4149 saxdb_write_int(ctx
, KEY_REGISTER_ON
, hi
->registered
);
4150 if (hi
->screen_width
)
4151 saxdb_write_int(ctx
, KEY_SCREEN_WIDTH
, hi
->screen_width
);
4152 if (hi
->table_width
)
4153 saxdb_write_int(ctx
, KEY_TABLE_WIDTH
, hi
->table_width
);
4154 flags
[0] = hi
->userlist_style
;
4156 saxdb_write_string(ctx
, KEY_USERLIST_STYLE
, flags
);
4157 saxdb_end_record(ctx
);
4163 static handle_merge_func_t
*handle_merge_func_list
;
4164 static void **handle_merge_func_list_extra
;
4165 static unsigned int handle_merge_func_size
= 0, handle_merge_func_used
= 0;
4168 reg_handle_merge_func(handle_merge_func_t func
, void *extra
)
4170 if (handle_merge_func_used
== handle_merge_func_size
) {
4171 if (handle_merge_func_size
) {
4172 handle_merge_func_size
<<= 1;
4173 handle_merge_func_list
= realloc(handle_merge_func_list
, handle_merge_func_size
*sizeof(handle_merge_func_t
));
4174 handle_merge_func_list_extra
= realloc(handle_merge_func_list_extra
, handle_merge_func_size
*sizeof(void*));
4176 handle_merge_func_size
= 8;
4177 handle_merge_func_list
= malloc(handle_merge_func_size
*sizeof(handle_merge_func_t
));
4178 handle_merge_func_list_extra
= malloc(handle_merge_func_size
*sizeof(void*));
4181 handle_merge_func_list
[handle_merge_func_used
] = func
;
4182 handle_merge_func_list_extra
[handle_merge_func_used
++] = extra
;
4185 static NICKSERV_FUNC(cmd_merge
)
4187 struct handle_info
*hi_from
, *hi_to
;
4188 struct userNode
*last_user
;
4189 struct userData
*cList
, *cListNext
;
4190 unsigned int ii
, jj
, n
;
4192 NICKSERV_MIN_PARMS(3);
4194 if (!(hi_from
= get_victim_oper(user
, argv
[1])))
4196 if (!(hi_to
= get_victim_oper(user
, argv
[2])))
4198 if (hi_to
== hi_from
) {
4199 reply("NSMSG_CANNOT_MERGE_SELF", hi_to
->handle
);
4203 for (n
=0; n
<handle_merge_func_used
; n
++)
4204 handle_merge_func_list
[n
](user
, hi_to
, hi_from
, handle_merge_func_list_extra
[n
]);
4206 /* Append "from" handle's nicks to "to" handle's nick list. */
4208 struct nick_info
*last_ni
;
4209 for (last_ni
=hi_to
->nicks
; last_ni
->next
; last_ni
=last_ni
->next
) ;
4210 last_ni
->next
= hi_from
->nicks
;
4212 while (hi_from
->nicks
) {
4213 hi_from
->nicks
->owner
= hi_to
;
4214 hi_from
->nicks
= hi_from
->nicks
->next
;
4217 /* Merge the hostmasks. */
4218 for (ii
=0; ii
<hi_from
->masks
->used
; ii
++) {
4219 char *mask
= hi_from
->masks
->list
[ii
];
4220 for (jj
=0; jj
<hi_to
->masks
->used
; jj
++)
4221 if (match_ircglobs(hi_to
->masks
->list
[jj
], mask
))
4223 if (jj
==hi_to
->masks
->used
) /* Nothing from the "to" handle covered this mask, so add it. */
4224 string_list_append(hi_to
->masks
, strdup(mask
));
4227 /* Merge the SSL fingerprints. */
4228 for (ii
=0; ii
<hi_from
->sslfps
->used
; ii
++) {
4229 char *sslfp
= hi_from
->sslfps
->list
[ii
];
4230 for (jj
=0; jj
<hi_to
->sslfps
->used
; jj
++)
4231 if (!irccasecmp(hi_to
->sslfps
->list
[jj
], sslfp
))
4233 if (jj
==hi_to
->sslfps
->used
) /* Nothing from the "to" handle covered this sslfp, so add it. */
4234 string_list_append(hi_to
->sslfps
, strdup(sslfp
));
4237 /* Merge the ignores. */
4238 for (ii
=0; ii
<hi_from
->ignores
->used
; ii
++) {
4239 char *ignore
= hi_from
->ignores
->list
[ii
];
4240 for (jj
=0; jj
<hi_to
->ignores
->used
; jj
++)
4241 if (match_ircglobs(hi_to
->ignores
->list
[jj
], ignore
))
4243 if (jj
==hi_to
->ignores
->used
) /* Nothing from the "to" handle covered this mask, so add it. */
4244 string_list_append(hi_to
->ignores
, strdup(ignore
));
4247 /* Merge the lists of authed users. */
4249 for (last_user
=hi_to
->users
; last_user
->next_authed
; last_user
=last_user
->next_authed
) ;
4250 last_user
->next_authed
= hi_from
->users
;
4252 hi_to
->users
= hi_from
->users
;
4254 /* Repoint the old "from" handle's users. */
4255 for (last_user
=hi_from
->users
; last_user
; last_user
=last_user
->next_authed
) {
4256 last_user
->handle_info
= hi_to
;
4258 hi_from
->users
= NULL
;
4260 /* Merge channel userlists. */
4261 for (cList
=hi_from
->channels
; cList
; cList
=cListNext
) {
4262 struct userData
*cList2
;
4263 cListNext
= cList
->u_next
;
4264 for (cList2
=hi_to
->channels
; cList2
; cList2
=cList2
->u_next
)
4265 if (cList
->channel
== cList2
->channel
)
4267 if (cList2
&& (cList2
->access
>= cList
->access
)) {
4268 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
);
4269 /* keep cList2 in hi_to; remove cList from hi_from */
4270 del_channel_user(cList
, 1);
4273 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
);
4274 /* remove the lower-ranking cList2 from hi_to */
4275 del_channel_user(cList2
, 1);
4277 log_module(NS_LOG
, LOG_INFO
, "Merge: %s had no access in %s", hi_to
->handle
, cList
->channel
->channel
->name
);
4279 /* cList needs to be moved from hi_from to hi_to */
4280 cList
->handle
= hi_to
;
4281 /* Remove from linked list for hi_from */
4282 assert(!cList
->u_prev
);
4283 hi_from
->channels
= cList
->u_next
;
4285 cList
->u_next
->u_prev
= cList
->u_prev
;
4286 /* Add to linked list for hi_to */
4287 cList
->u_prev
= NULL
;
4288 cList
->u_next
= hi_to
->channels
;
4289 if (hi_to
->channels
)
4290 hi_to
->channels
->u_prev
= cList
;
4291 hi_to
->channels
= cList
;
4295 /* Do they get an OpServ level promotion? */
4296 if (hi_from
->opserv_level
> hi_to
->opserv_level
)
4297 hi_to
->opserv_level
= hi_from
->opserv_level
;
4299 /* What about last seen time? */
4300 if (hi_from
->lastseen
> hi_to
->lastseen
)
4301 hi_to
->lastseen
= hi_from
->lastseen
;
4303 /* New karma is the sum of the two original karmas. */
4304 hi_to
->karma
+= hi_from
->karma
;
4306 /* Does a fakehost carry over? (This intentionally doesn't set it
4307 * for users previously attached to hi_to. They'll just have to
4310 if (hi_from
->fakehost
&& !hi_to
->fakehost
)
4311 hi_to
->fakehost
= strdup(hi_from
->fakehost
);
4313 /* Notify of success. */
4314 reply("NSMSG_HANDLES_MERGED", hi_from
->handle
, hi_to
->handle
);
4315 global_message_args(MESSAGE_RECIPIENT_OPERS
, "NSMSG_ACCOUNT_MERGED", user
->nick
,
4316 user
->handle_info
->handle
, hi_from
->handle
, hi_to
->handle
);
4318 /* Unregister the "from" handle. */
4319 nickserv_unregister_handle(hi_from
, NULL
, cmd
->parent
->bot
);
4320 /* TODO: fix it so that if the ldap delete in nickserv_unregister_handle fails,
4321 * the process isn't completed.
4327 struct nickserv_discrim
{
4328 unsigned long flags_on
, flags_off
;
4329 time_t min_registered
, max_registered
;
4332 int min_level
, max_level
;
4333 int min_karma
, max_karma
;
4334 enum { SUBSET
, EXACT
, SUPERSET
, LASTQUIT
} hostmask_type
;
4335 const char *nickmask
;
4336 const char *hostmask
;
4337 const char *handlemask
;
4338 const char *emailmask
;
4339 const char *titlemask
;
4340 const char *setwhat
;
4344 unsigned int inldap
;
4348 typedef void (*discrim_search_func
)(struct userNode
*source
, struct handle_info
*hi
, struct nickserv_discrim
*discrim
);
4350 struct discrim_apply_info
{
4351 struct nickserv_discrim
*discrim
;
4352 discrim_search_func func
;
4353 struct userNode
*source
;
4354 unsigned int matched
;
4357 static struct nickserv_discrim
*
4358 nickserv_discrim_create(struct svccmd
*cmd
, struct userNode
*user
, unsigned int argc
, char *argv
[])
4361 struct nickserv_discrim
*discrim
;
4363 discrim
= malloc(sizeof(*discrim
));
4364 memset(discrim
, 0, sizeof(*discrim
));
4365 discrim
->min_level
= 0;
4366 discrim
->max_level
= INT_MAX
;
4367 discrim
->limit
= 50;
4368 discrim
->min_registered
= 0;
4369 discrim
->max_registered
= INT_MAX
;
4370 discrim
->lastseen
= LONG_MAX
;
4371 discrim
->min_karma
= INT_MIN
;
4372 discrim
->max_karma
= INT_MAX
;
4375 discrim
->inldap
= 2;
4378 for (i
=0; i
<argc
; i
++) {
4379 if (i
== argc
- 1) {
4380 reply("MSG_MISSING_PARAMS", argv
[i
]);
4383 if (!irccasecmp(argv
[i
], "limit")) {
4384 discrim
->limit
= strtoul(argv
[++i
], NULL
, 0);
4385 } else if (!irccasecmp(argv
[i
], "flags")) {
4386 nickserv_modify_handle_flags(user
, nickserv
, argv
[++i
], &discrim
->flags_on
, &discrim
->flags_off
);
4387 } else if (!irccasecmp(argv
[i
], "registered")) {
4388 const char *cmp
= argv
[++i
];
4389 if (cmp
[0] == '<') {
4390 if (cmp
[1] == '=') {
4391 discrim
->min_registered
= now
- ParseInterval(cmp
+2);
4393 discrim
->min_registered
= now
- ParseInterval(cmp
+1) + 1;
4395 } else if (cmp
[0] == '=') {
4396 discrim
->min_registered
= discrim
->max_registered
= now
- ParseInterval(cmp
+1);
4397 } else if (cmp
[0] == '>') {
4398 if (cmp
[1] == '=') {
4399 discrim
->max_registered
= now
- ParseInterval(cmp
+2);
4401 discrim
->max_registered
= now
- ParseInterval(cmp
+1) - 1;
4404 reply("MSG_INVALID_CRITERIA", cmp
);
4406 } else if (!irccasecmp(argv
[i
], "seen")) {
4407 discrim
->lastseen
= now
- ParseInterval(argv
[++i
]);
4408 } else if (!nickserv_conf
.disable_nicks
&& !irccasecmp(argv
[i
], "nickmask")) {
4409 discrim
->nickmask
= argv
[++i
];
4410 } else if (!irccasecmp(argv
[i
], "setwhat")) {
4411 discrim
->setwhat
= argv
[++i
];
4412 if (!(dict_find(nickserv_opt_dict
, discrim
->setwhat
, NULL
))) {
4413 reply("NSMSG_INVALID_OPTION", discrim
->setwhat
);
4416 } else if (!irccasecmp(argv
[i
], "setvalue")) {
4417 discrim
->setval
= argv
[++i
];
4418 } else if (!irccasecmp(argv
[i
], "hostmask")) {
4420 if (!irccasecmp(argv
[i
], "exact")) {
4421 if (i
== argc
- 1) {
4422 reply("MSG_MISSING_PARAMS", argv
[i
]);
4425 discrim
->hostmask_type
= EXACT
;
4426 } else if (!irccasecmp(argv
[i
], "subset")) {
4427 if (i
== argc
- 1) {
4428 reply("MSG_MISSING_PARAMS", argv
[i
]);
4431 discrim
->hostmask_type
= SUBSET
;
4432 } else if (!irccasecmp(argv
[i
], "superset")) {
4433 if (i
== argc
- 1) {
4434 reply("MSG_MISSING_PARAMS", argv
[i
]);
4437 discrim
->hostmask_type
= SUPERSET
;
4438 } else if (!irccasecmp(argv
[i
], "lastquit") || !irccasecmp(argv
[i
], "lastauth")) {
4439 if (i
== argc
- 1) {
4440 reply("MSG_MISSING_PARAMS", argv
[i
]);
4443 discrim
->hostmask_type
= LASTQUIT
;
4446 discrim
->hostmask_type
= SUPERSET
;
4448 discrim
->hostmask
= argv
[++i
];
4449 } else if (!irccasecmp(argv
[i
], "handlemask") || !irccasecmp(argv
[i
], "accountmask") || !irccasecmp(argv
[i
], "account")) {
4450 if (!irccasecmp(argv
[++i
], "*")) {
4451 discrim
->handlemask
= 0;
4453 discrim
->handlemask
= argv
[i
];
4455 } else if (!irccasecmp(argv
[i
], "email")) {
4456 if (user
->handle_info
->opserv_level
< nickserv_conf
.email_search_level
) {
4457 reply("MSG_NO_SEARCH_ACCESS", "email");
4459 } else if (!irccasecmp(argv
[++i
], "*")) {
4460 discrim
->emailmask
= 0;
4462 discrim
->emailmask
= argv
[i
];
4464 } else if (!irccasecmp(argv
[i
], "title")) {
4465 if (!irccasecmp(argv
[++i
], "*")) {
4466 discrim
->titlemask
= 0;
4468 discrim
->titlemask
= argv
[i
];
4470 } else if (!irccasecmp(argv
[i
], "access")) {
4471 const char *cmp
= argv
[++i
];
4472 if (cmp
[0] == '<') {
4473 if (discrim
->min_level
== 0) discrim
->min_level
= 1;
4474 if (cmp
[1] == '=') {
4475 discrim
->max_level
= strtoul(cmp
+2, NULL
, 0);
4477 discrim
->max_level
= strtoul(cmp
+1, NULL
, 0) - 1;
4479 } else if (cmp
[0] == '=') {
4480 discrim
->min_level
= discrim
->max_level
= strtoul(cmp
+1, NULL
, 0);
4481 } else if (cmp
[0] == '>') {
4482 if (cmp
[1] == '=') {
4483 discrim
->min_level
= strtoul(cmp
+2, NULL
, 0);
4485 discrim
->min_level
= strtoul(cmp
+1, NULL
, 0) + 1;
4488 reply("MSG_INVALID_CRITERIA", cmp
);
4490 } else if (!irccasecmp(argv
[i
], "karma")) {
4491 const char *cmp
= argv
[++i
];
4492 if (cmp
[0] == '<') {
4493 if (cmp
[1] == '=') {
4494 discrim
->max_karma
= strtoul(cmp
+2, NULL
, 0);
4496 discrim
->max_karma
= strtoul(cmp
+1, NULL
, 0) - 1;
4498 } else if (cmp
[0] == '=') {
4499 discrim
->min_karma
= discrim
->max_karma
= strtoul(cmp
+1, NULL
, 0);
4500 } else if (cmp
[0] == '>') {
4501 if (cmp
[1] == '=') {
4502 discrim
->min_karma
= strtoul(cmp
+2, NULL
, 0);
4504 discrim
->min_karma
= strtoul(cmp
+1, NULL
, 0) + 1;
4507 send_message(user
, nickserv
, "MSG_INVALID_CRITERIA", cmp
);
4510 } else if (nickserv_conf
.ldap_enable
&& !irccasecmp(argv
[i
], "inldap")) {
4512 if(true_string(argv
[i
])) {
4513 discrim
->inldap
= 1;
4515 else if (false_string(argv
[i
])) {
4516 discrim
->inldap
= 0;
4519 reply("MSG_INVALID_BINARY", argv
[i
]);
4523 reply("MSG_INVALID_CRITERIA", argv
[i
]);
4534 nickserv_discrim_match(struct nickserv_discrim
*discrim
, struct handle_info
*hi
)
4538 if (hi
->fakehost
&& (hi
->fakehost
[0] == '.'))
4539 title
= hi
->fakehost
+ 1;
4541 if (((discrim
->flags_on
& hi
->flags
) != discrim
->flags_on
)
4542 || (discrim
->flags_off
& hi
->flags
)
4543 || (discrim
->min_registered
> hi
->registered
)
4544 || (discrim
->max_registered
< hi
->registered
)
4545 || (discrim
->lastseen
< (hi
->users
?now
:hi
->lastseen
))
4546 || (discrim
->handlemask
&& !match_ircglob(hi
->handle
, discrim
->handlemask
))
4547 || (discrim
->emailmask
&& (!hi
->email_addr
|| !match_ircglob(hi
->email_addr
, discrim
->emailmask
)))
4548 || (discrim
->titlemask
&& (!title
|| !match_ircglob(title
, discrim
->titlemask
)))
4549 || (discrim
->min_level
> hi
->opserv_level
)
4550 || (discrim
->max_level
< hi
->opserv_level
)
4551 || (discrim
->min_karma
> hi
->karma
)
4552 || (discrim
->max_karma
< hi
->karma
)
4556 if (discrim
->hostmask
) {
4558 for (i
=0; i
<hi
->masks
->used
; i
++) {
4559 const char *mask
= hi
->masks
->list
[i
];
4560 if ((discrim
->hostmask_type
== SUBSET
)
4561 && (match_ircglobs(discrim
->hostmask
, mask
))) break;
4562 else if ((discrim
->hostmask_type
== EXACT
)
4563 && !irccasecmp(discrim
->hostmask
, mask
)) break;
4564 else if ((discrim
->hostmask_type
== SUPERSET
)
4565 && (match_ircglobs(mask
, discrim
->hostmask
))) break;
4566 else if ((discrim
->hostmask_type
== LASTQUIT
)
4567 && (match_ircglobs(discrim
->hostmask
, hi
->last_quit_host
))) break;
4569 if (i
==hi
->masks
->used
) return 0;
4571 if (discrim
->nickmask
) {
4572 struct nick_info
*nick
= hi
->nicks
;
4574 if (match_ircglob(nick
->nick
, discrim
->nickmask
)) break;
4577 if (!nick
) return 0;
4580 if(nickserv_conf
.ldap_enable
&& discrim
->inldap
!= 2) {
4582 rc
= ldap_get_user_info(hi
->handle
, NULL
);
4583 if(discrim
->inldap
== 1 && rc
!= LDAP_SUCCESS
)
4585 if(discrim
->inldap
== 0 && rc
== LDAP_SUCCESS
)
4594 nickserv_discrim_search(struct nickserv_discrim
*discrim
, discrim_search_func dsf
, struct userNode
*source
)
4596 dict_iterator_t it
, next
;
4597 unsigned int matched
;
4599 for (it
= dict_first(nickserv_handle_dict
), matched
= 0;
4600 it
&& (matched
< discrim
->limit
);
4602 next
= iter_next(it
);
4603 if (nickserv_discrim_match(discrim
, iter_data(it
))) {
4604 dsf(source
, iter_data(it
), discrim
);
4612 search_print_func(struct userNode
*source
, struct handle_info
*match
, UNUSED_ARG(struct nickserv_discrim
*discrim
))
4614 send_message(source
, nickserv
, "NSMSG_SEARCH_MATCH", match
->handle
);
4618 search_count_func(UNUSED_ARG(struct userNode
*source
), UNUSED_ARG(struct handle_info
*match
), UNUSED_ARG(struct nickserv_discrim
*discrim
))
4623 search_unregister_func (struct userNode
*source
, struct handle_info
*match
, UNUSED_ARG(struct nickserv_discrim
*discrim
))
4625 if (oper_has_access(source
, nickserv
, match
->opserv_level
, 0))
4626 nickserv_unregister_handle(match
, source
, nickserv
); // XXX nickserv hard coded
4631 search_add2ldap_func (struct userNode
*source
, struct handle_info
*match
, UNUSED_ARG(struct nickserv_discrim
*discrim
))
4634 if(match
->email_addr
&& match
->passwd
&& match
->handle
) {
4635 rc
= ldap_do_add(match
->handle
, match
->passwd
, match
->email_addr
);
4636 if(rc
!= LDAP_SUCCESS
) {
4637 send_message(source
, nickserv
, "NSMSG_LDAP_FAIL_ADD", match
->handle
, ldap_err2string(rc
));
4644 search_set_func (struct userNode
*source
, struct handle_info
*match
, struct nickserv_discrim
*discrim
)
4649 if (!(opt
= dict_find(nickserv_opt_dict
, discrim
->setwhat
, NULL
))) {
4653 oargv
[0] = (char *)discrim
->setwhat
;
4654 oargv
[1] = (char *)discrim
->setval
;
4656 opt(discrim
->cmd
, source
, match
, 1, 1, 2, oargv
);
4660 nickserv_sort_accounts_by_access(const void *a
, const void *b
)
4662 const struct handle_info
*hi_a
= *(const struct handle_info
**)a
;
4663 const struct handle_info
*hi_b
= *(const struct handle_info
**)b
;
4664 if (hi_a
->opserv_level
!= hi_b
->opserv_level
)
4665 return hi_b
->opserv_level
- hi_a
->opserv_level
;
4666 return irccasecmp(hi_a
->handle
, hi_b
->handle
);
4670 nickserv_show_oper_accounts(struct userNode
*user
, struct svccmd
*cmd
)
4672 struct handle_info_list hil
;
4673 struct helpfile_table tbl
;
4678 memset(&hil
, 0, sizeof(hil
));
4679 for (it
= dict_first(nickserv_handle_dict
); it
; it
= iter_next(it
)) {
4680 struct handle_info
*hi
= iter_data(it
);
4681 if (hi
->opserv_level
)
4682 handle_info_list_append(&hil
, hi
);
4684 qsort(hil
.list
, hil
.used
, sizeof(hil
.list
[0]), nickserv_sort_accounts_by_access
);
4685 tbl
.length
= hil
.used
+ 1;
4687 tbl
.flags
= TABLE_NO_FREE
| TABLE_REPEAT_ROWS
| TABLE_REPEAT_HEADERS
;
4688 tbl
.contents
= malloc(tbl
.length
* sizeof(tbl
.contents
[0]));
4689 tbl
.contents
[0] = ary
= malloc(tbl
.width
* sizeof(ary
[0]));
4692 for (ii
= 0; ii
< hil
.used
; ) {
4693 ary
= malloc(tbl
.width
* sizeof(ary
[0]));
4694 ary
[0] = hil
.list
[ii
]->handle
;
4695 ary
[1] = strtab(hil
.list
[ii
]->opserv_level
);
4696 tbl
.contents
[++ii
] = ary
;
4698 table_send(cmd
->parent
->bot
, user
->nick
, 0, NULL
, tbl
);
4699 /*reply("MSG_MATCH_COUNT", hil.used); */
4700 for (ii
= 0; ii
< hil
.used
; ii
++)
4701 free(tbl
.contents
[ii
]);
4706 static NICKSERV_FUNC(cmd_search
)
4708 struct nickserv_discrim
*discrim
;
4709 discrim_search_func action
;
4710 struct svccmd
*subcmd
;
4711 unsigned int matches
;
4714 NICKSERV_MIN_PARMS(3);
4715 sprintf(buf
, "search %s", argv
[1]);
4716 subcmd
= dict_find(nickserv_service
->commands
, buf
, NULL
);
4717 if (!irccasecmp(argv
[1], "print"))
4718 action
= search_print_func
;
4719 else if (!irccasecmp(argv
[1], "count"))
4720 action
= search_count_func
;
4721 else if (!irccasecmp(argv
[1], "unregister"))
4722 action
= search_unregister_func
;
4723 else if (!irccasecmp(argv
[1], "set"))
4724 action
= search_set_func
;
4726 else if (nickserv_conf
.ldap_enable
&& !irccasecmp(argv
[1], "add2ldap"))
4727 action
= search_add2ldap_func
;
4730 reply("NSMSG_INVALID_ACTION", argv
[1]);
4734 if (subcmd
&& !svccmd_can_invoke(user
, nickserv
, subcmd
, NULL
, SVCCMD_NOISY
))
4737 discrim
= nickserv_discrim_create(cmd
, user
, argc
-2, argv
+2);
4741 if (action
== search_print_func
)
4742 reply("NSMSG_ACCOUNT_SEARCH_RESULTS");
4743 else if (action
== search_count_func
)
4744 discrim
->limit
= INT_MAX
;
4745 else if ((action
== search_set_func
) && (!(discrim
->setwhat
) || !(discrim
->setval
)))
4746 return reply("MSG_MISSING_PARAMS", argv
[1]);
4748 matches
= nickserv_discrim_search(discrim
, action
, user
);
4751 reply("MSG_MATCH_COUNT", matches
);
4753 reply("MSG_NO_MATCHES");
4759 static MODCMD_FUNC(cmd_checkpass
)
4761 struct handle_info
*hi
;
4763 NICKSERV_MIN_PARMS(3);
4764 if (!(hi
= get_handle_info(argv
[1]))) {
4765 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
4768 if (checkpass(argv
[2], hi
->passwd
))
4769 reply("CHECKPASS_YES");
4771 reply("CHECKPASS_NO");
4776 static MODCMD_FUNC(cmd_checkemail
)
4778 struct handle_info
*hi
;
4780 NICKSERV_MIN_PARMS(3);
4781 if (!(hi
= modcmd_get_handle_info(user
, argv
[1]))) {
4784 if (!hi
->email_addr
)
4785 reply("CHECKEMAIL_NOT_SET");
4786 else if (!irccasecmp(argv
[2], hi
->email_addr
))
4787 reply("CHECKEMAIL_YES");
4789 reply("CHECKEMAIL_NO");
4794 nickserv_db_read_handle(char *handle
, dict_t obj
)
4797 struct string_list
*masks
, *sslfps
, *slist
, *ignores
;
4798 struct handle_info
*hi
;
4799 struct userNode
*authed_users
;
4800 struct userData
*channel_list
;
4803 unsigned long int id
;
4806 char *setter
, *note
;
4809 str
= database_get_data(obj
, KEY_ID
, RECDB_QSTRING
);
4810 id
= str
? strtoul(str
, NULL
, 0) : 0;
4811 str
= database_get_data(obj
, KEY_PASSWD
, RECDB_QSTRING
);
4813 log_module(NS_LOG
, LOG_WARNING
, "did not find a password for %s -- skipping user.", handle
);
4816 if ((hi
= get_handle_info(handle
))) {
4817 authed_users
= hi
->users
;
4818 channel_list
= hi
->channels
;
4820 hi
->channels
= NULL
;
4821 dict_remove(nickserv_handle_dict
, hi
->handle
);
4823 authed_users
= NULL
;
4824 channel_list
= NULL
;
4826 if(nickserv_conf
.force_handles_lowercase
)
4827 irc_strtolower(handle
);
4828 hi
= register_handle(handle
, str
, id
);
4830 hi
->users
= authed_users
;
4831 while (authed_users
) {
4832 authed_users
->handle_info
= hi
;
4833 authed_users
= authed_users
->next_authed
;
4836 hi
->channels
= channel_list
;
4837 masks
= database_get_data(obj
, KEY_MASKS
, RECDB_STRING_LIST
);
4838 hi
->masks
= masks
? string_list_copy(masks
) : alloc_string_list(1);
4839 sslfps
= database_get_data(obj
, KEY_SSLFPS
, RECDB_STRING_LIST
);
4840 hi
->sslfps
= sslfps
? string_list_copy(sslfps
) : alloc_string_list(1);
4841 ignores
= database_get_data(obj
, KEY_IGNORES
, RECDB_STRING_LIST
);
4842 hi
->ignores
= ignores
? string_list_copy(ignores
) : alloc_string_list(1);
4843 str
= database_get_data(obj
, KEY_MAXLOGINS
, RECDB_QSTRING
);
4844 hi
->maxlogins
= str
? strtoul(str
, NULL
, 0) : 0;
4845 str
= database_get_data(obj
, KEY_LANGUAGE
, RECDB_QSTRING
);
4846 hi
->language
= language_find(str
? str
: "C");
4847 str
= database_get_data(obj
, KEY_OPSERV_LEVEL
, RECDB_QSTRING
);
4848 hi
->opserv_level
= str
? strtoul(str
, NULL
, 0) : 0;
4849 str
= database_get_data(obj
, KEY_INFO
, RECDB_QSTRING
);
4851 hi
->infoline
= strdup(str
);
4852 str
= database_get_data(obj
, KEY_REGISTER_ON
, RECDB_QSTRING
);
4853 hi
->registered
= str
? (time_t)strtoul(str
, NULL
, 0) : now
;
4854 str
= database_get_data(obj
, KEY_LAST_SEEN
, RECDB_QSTRING
);
4855 hi
->lastseen
= str
? (time_t)strtoul(str
, NULL
, 0) : hi
->registered
;
4856 str
= database_get_data(obj
, KEY_KARMA
, RECDB_QSTRING
);
4857 hi
->karma
= str
? strtoul(str
, NULL
, 0) : 0;
4858 /* We want to read the nicks even if disable_nicks is set. This is so
4859 * that we don't lose the nick data entirely. */
4860 obj2
= database_get_data(obj
, KEY_NICKS_EX
, RECDB_OBJECT
);
4861 for(it
= dict_first(obj2
); it
; it
= iter_next(it
))
4863 struct record_data
*rd
= iter_data(it
);
4864 struct nick_info
* ni
;
4866 register_nick(iter_key(it
), hi
);
4867 ni
= get_nick_info(iter_key(it
));
4872 str
= database_get_data(rd
->d
.object
, KEY_REGISTER_ON
, RECDB_QSTRING
);
4873 ni
->registered
= str
? (time_t)strtoul(str
, NULL
, 0) : now
;
4874 str
= database_get_data(rd
->d
.object
, KEY_LAST_SEEN
, RECDB_QSTRING
);
4875 ni
->lastseen
= str
? (time_t)strtoul(str
, NULL
, 0) : ni
->registered
;
4878 slist
= database_get_data(obj
, KEY_NICKS
, RECDB_STRING_LIST
);
4880 for (ii
=0; ii
<slist
->used
; ii
++) {
4881 struct nick_info
* ni
;
4883 register_nick(slist
->list
[ii
], hi
);
4884 ni
= get_nick_info(slist
->list
[ii
]);
4889 ni
->registered
= hi
->registered
;
4890 ni
->lastseen
= ni
->registered
;
4894 str
= database_get_data(obj
, KEY_FLAGS
, RECDB_QSTRING
);
4896 for (ii
=0; str
[ii
]; ii
++)
4897 hi
->flags
|= 1 << (handle_inverse_flags
[(unsigned char)str
[ii
]] - 1);
4899 str
= database_get_data(obj
, KEY_USERLIST_STYLE
, RECDB_QSTRING
);
4900 hi
->userlist_style
= str
? str
[0] : HI_DEFAULT_STYLE
;
4901 str
= database_get_data(obj
, KEY_ANNOUNCEMENTS
, RECDB_QSTRING
);
4902 hi
->announcements
= str
? str
[0] : '?';
4903 str
= database_get_data(obj
, KEY_SCREEN_WIDTH
, RECDB_QSTRING
);
4904 hi
->screen_width
= str
? strtoul(str
, NULL
, 0) : 0;
4905 str
= database_get_data(obj
, KEY_TABLE_WIDTH
, RECDB_QSTRING
);
4906 hi
->table_width
= str
? strtoul(str
, NULL
, 0) : 0;
4907 str
= database_get_data(obj
, KEY_LAST_QUIT_HOST
, RECDB_QSTRING
);
4909 str
= database_get_data(obj
, KEY_LAST_AUTHED_HOST
, RECDB_QSTRING
);
4911 safestrncpy(hi
->last_quit_host
, str
, sizeof(hi
->last_quit_host
));
4912 str
= database_get_data(obj
, KEY_EMAIL_ADDR
, RECDB_QSTRING
);
4914 nickserv_set_email_addr(hi
, str
);
4915 str
= database_get_data(obj
, KEY_EPITHET
, RECDB_QSTRING
);
4917 hi
->epithet
= strdup(str
);
4918 subdb
= database_get_data(obj
, KEY_NOTE_NOTE
, RECDB_OBJECT
);
4920 setter
= database_get_data(subdb
, KEY_NOTE_SETTER
, RECDB_QSTRING
);
4921 str
= database_get_data(subdb
, KEY_NOTE_DATE
, RECDB_QSTRING
);
4922 date
= str
? (time_t)strtoul(str
, NULL
, 0) : now
;
4923 note
= database_get_data(subdb
, KEY_NOTE_NOTE
, RECDB_QSTRING
);
4924 if (setter
&& date
&& note
)
4926 if (!(hi
->note
= nickserv_add_note(setter
, date
, note
)))
4931 str
= database_get_data(obj
, KEY_FAKEHOST
, RECDB_QSTRING
);
4933 hi
->fakehost
= strdup(str
);
4935 subdb
= database_get_data(obj
, KEY_COOKIE
, RECDB_OBJECT
);
4937 const char *data
, *type
, *expires
, *cookie_str
;
4938 struct handle_cookie
*cookie
;
4940 cookie
= calloc(1, sizeof(*cookie
));
4941 type
= database_get_data(subdb
, KEY_COOKIE_TYPE
, RECDB_QSTRING
);
4942 data
= database_get_data(subdb
, KEY_COOKIE_DATA
, RECDB_QSTRING
);
4943 expires
= database_get_data(subdb
, KEY_COOKIE_EXPIRES
, RECDB_QSTRING
);
4944 cookie_str
= database_get_data(subdb
, KEY_COOKIE
, RECDB_QSTRING
);
4945 if (!type
|| !expires
|| !cookie_str
) {
4946 log_module(NS_LOG
, LOG_ERROR
, "Missing field(s) from cookie for account %s; dropping cookie.", hi
->handle
);
4949 if (!irccasecmp(type
, KEY_ACTIVATION
))
4950 cookie
->type
= ACTIVATION
;
4951 else if (!irccasecmp(type
, KEY_PASSWORD_CHANGE
))
4952 cookie
->type
= PASSWORD_CHANGE
;
4953 else if (!irccasecmp(type
, KEY_EMAIL_CHANGE
))
4954 cookie
->type
= EMAIL_CHANGE
;
4955 else if (!irccasecmp(type
, KEY_ALLOWAUTH
))
4956 cookie
->type
= ALLOWAUTH
;
4958 log_module(NS_LOG
, LOG_ERROR
, "Invalid cookie type %s for account %s; dropping cookie.", type
, handle
);
4961 cookie
->expires
= strtoul(expires
, NULL
, 0);
4962 if (cookie
->expires
< now
)
4965 cookie
->data
= strdup(data
);
4966 safestrncpy(cookie
->cookie
, cookie_str
, sizeof(cookie
->cookie
));
4970 nickserv_bake_cookie(cookie
);
4972 nickserv_free_cookie(cookie
);
4977 nickserv_saxdb_read(dict_t db
) {
4979 struct record_data
*rd
;
4982 for (it
=dict_first(db
); it
; it
=iter_next(it
)) {
4984 handle
= strdup(iter_key(it
));
4985 nickserv_db_read_handle(handle
, rd
->d
.object
);
4991 static NICKSERV_FUNC(cmd_mergedb
)
4993 struct timeval start
, stop
;
4996 NICKSERV_MIN_PARMS(2);
4997 gettimeofday(&start
, NULL
);
4998 if (!(db
= parse_database(argv
[1]))) {
4999 reply("NSMSG_DB_UNREADABLE", argv
[1]);
5002 nickserv_saxdb_read(db
);
5004 gettimeofday(&stop
, NULL
);
5005 stop
.tv_sec
-= start
.tv_sec
;
5006 stop
.tv_usec
-= start
.tv_usec
;
5007 if (stop
.tv_usec
< 0) {
5009 stop
.tv_usec
+= 1000000;
5011 reply("NSMSG_DB_MERGED", argv
[1], stop
.tv_sec
, stop
.tv_usec
/1000);
5016 expire_handles(UNUSED_ARG(void *data
))
5018 dict_iterator_t it
, next
;
5020 struct handle_info
*hi
;
5022 for (it
=dict_first(nickserv_handle_dict
); it
; it
=next
) {
5023 next
= iter_next(it
);
5025 if ((hi
->opserv_level
> 0)
5027 || HANDLE_FLAGGED(hi
, FROZEN
)
5028 || HANDLE_FLAGGED(hi
, NODELETE
)) {
5031 expiry
= hi
->channels
? nickserv_conf
.handle_expire_delay
: nickserv_conf
.nochan_handle_expire_delay
;
5032 if ((now
- hi
->lastseen
) > expiry
) {
5033 log_module(NS_LOG
, LOG_INFO
, "Expiring account %s for inactivity.", hi
->handle
);
5034 nickserv_unregister_handle(hi
, NULL
, NULL
);
5038 if (nickserv_conf
.handle_expire_frequency
)
5039 timeq_add(now
+ nickserv_conf
.handle_expire_frequency
, expire_handles
, NULL
);
5043 expire_nicks(UNUSED_ARG(void *data
))
5045 dict_iterator_t it
, next
;
5046 time_t expiry
= nickserv_conf
.nick_expire_delay
;
5047 struct nick_info
*ni
;
5048 struct userNode
*ui
;
5050 if (!(nickserv_conf
.expire_nicks
))
5053 for (it
=dict_first(nickserv_nick_dict
); it
; it
=next
) {
5054 next
= iter_next(it
);
5056 if ((ni
->owner
->opserv_level
> 0)
5057 || ((ui
= GetUserH(ni
->nick
)) && (ui
->handle_info
) && (ui
->handle_info
== ni
->owner
))
5058 || HANDLE_FLAGGED(ni
->owner
, FROZEN
)
5059 || HANDLE_FLAGGED(ni
->owner
, NODELETE
)) {
5062 if ((now
- ni
->lastseen
) > expiry
) {
5063 log_module(NS_LOG
, LOG_INFO
, "Expiring nick %s for inactivity.", ni
->nick
);
5068 if (nickserv_conf
.nick_expire_frequency
&& nickserv_conf
.expire_nicks
)
5069 timeq_add(now
+ nickserv_conf
.nick_expire_frequency
, expire_nicks
, NULL
);
5073 nickserv_load_dict(const char *fname
)
5077 if (!(file
= fopen(fname
, "r"))) {
5078 log_module(NS_LOG
, LOG_ERROR
, "Unable to open dictionary file %s: %s", fname
, strerror(errno
));
5081 while (fgets(line
, sizeof(line
), file
)) {
5084 if (line
[strlen(line
)-1] == '\n')
5085 line
[strlen(line
)-1] = 0;
5086 dict_insert(nickserv_conf
.weak_password_dict
, strdup(line
), NULL
);
5089 log_module(NS_LOG
, LOG_INFO
, "Loaded %d words into weak password dictionary.", dict_size(nickserv_conf
.weak_password_dict
));
5092 static enum reclaim_action
5093 reclaim_action_from_string(const char *str
) {
5095 return RECLAIM_NONE
;
5096 else if (!irccasecmp(str
, "warn"))
5097 return RECLAIM_WARN
;
5098 else if (!irccasecmp(str
, "svsnick"))
5099 return RECLAIM_SVSNICK
;
5100 else if (!irccasecmp(str
, "kill"))
5101 return RECLAIM_KILL
;
5103 return RECLAIM_NONE
;
5107 nickserv_conf_read(void)
5109 dict_t conf_node
, child
;
5112 struct string_list
*strlist
;
5114 if (!(conf_node
= conf_get_data(NICKSERV_CONF_NAME
, RECDB_OBJECT
))) {
5115 log_module(NS_LOG
, LOG_ERROR
, "config node `%s' is missing or has wrong type.", NICKSERV_CONF_NAME
);
5118 str
= database_get_data(conf_node
, KEY_VALID_HANDLE_REGEX
, RECDB_QSTRING
);
5120 str
= database_get_data(conf_node
, KEY_VALID_ACCOUNT_REGEX
, RECDB_QSTRING
);
5121 if (nickserv_conf
.valid_handle_regex_set
)
5122 regfree(&nickserv_conf
.valid_handle_regex
);
5124 int err
= regcomp(&nickserv_conf
.valid_handle_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
5125 nickserv_conf
.valid_handle_regex_set
= !err
;
5126 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_account_regex (error %d)", err
);
5128 nickserv_conf
.valid_handle_regex_set
= 0;
5130 str
= database_get_data(conf_node
, KEY_VALID_NICK_REGEX
, RECDB_QSTRING
);
5131 if (nickserv_conf
.valid_nick_regex_set
)
5132 regfree(&nickserv_conf
.valid_nick_regex
);
5134 int err
= regcomp(&nickserv_conf
.valid_nick_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
5135 nickserv_conf
.valid_nick_regex_set
= !err
;
5136 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_nick_regex (error %d)", err
);
5138 nickserv_conf
.valid_nick_regex_set
= 0;
5140 str
= database_get_data(conf_node
, KEY_VALID_FAKEHOST_REGEX
, RECDB_QSTRING
);
5141 if (nickserv_conf
.valid_fakehost_regex_set
)
5142 regfree(&nickserv_conf
.valid_fakehost_regex
);
5144 int err
= regcomp(&nickserv_conf
.valid_fakehost_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
5145 nickserv_conf
.valid_fakehost_regex_set
= !err
;
5146 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_fakehost_regex (error %d)", err
);
5148 nickserv_conf
.valid_fakehost_regex_set
= 0;
5150 str
= database_get_data(conf_node
, KEY_NICKS_PER_HANDLE
, RECDB_QSTRING
);
5152 str
= database_get_data(conf_node
, KEY_NICKS_PER_ACCOUNT
, RECDB_QSTRING
);
5153 nickserv_conf
.nicks_per_handle
= str
? strtoul(str
, NULL
, 0) : 4;
5154 str
= database_get_data(conf_node
, KEY_DISABLE_NICKS
, RECDB_QSTRING
);
5155 nickserv_conf
.disable_nicks
= str
? strtoul(str
, NULL
, 0) : 0;
5156 str
= database_get_data(conf_node
, KEY_DEFAULT_HOSTMASK
, RECDB_QSTRING
);
5157 nickserv_conf
.default_hostmask
= str
? !disabled_string(str
) : 0;
5158 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_LENGTH
, RECDB_QSTRING
);
5159 nickserv_conf
.password_min_length
= str
? strtoul(str
, NULL
, 0) : 0;
5160 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_DIGITS
, RECDB_QSTRING
);
5161 nickserv_conf
.password_min_digits
= str
? strtoul(str
, NULL
, 0) : 0;
5162 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_UPPER
, RECDB_QSTRING
);
5163 nickserv_conf
.password_min_upper
= str
? strtoul(str
, NULL
, 0) : 0;
5164 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_LOWER
, RECDB_QSTRING
);
5165 nickserv_conf
.password_min_lower
= str
? strtoul(str
, NULL
, 0) : 0;
5166 str
= database_get_data(conf_node
, KEY_DB_BACKUP_FREQ
, RECDB_QSTRING
);
5167 nickserv_conf
.db_backup_frequency
= str
? ParseInterval(str
) : 7200;
5168 str
= database_get_data(conf_node
, KEY_MODOPER_LEVEL
, RECDB_QSTRING
);
5169 nickserv_conf
.modoper_level
= str
? strtoul(str
, NULL
, 0) : 900;
5170 str
= database_get_data(conf_node
, KEY_SET_EPITHET_LEVEL
, RECDB_QSTRING
);
5171 nickserv_conf
.set_epithet_level
= str
? strtoul(str
, NULL
, 0) : 1;
5172 str
= database_get_data(conf_node
, KEY_SET_TITLE_LEVEL
, RECDB_QSTRING
);
5173 nickserv_conf
.set_title_level
= str
? strtoul(str
, NULL
, 0) : 900;
5174 str
= database_get_data(conf_node
, KEY_SET_FAKEHOST_LEVEL
, RECDB_QSTRING
);
5175 nickserv_conf
.set_fakehost_level
= str
? strtoul(str
, NULL
, 0) : 1000;
5176 str
= database_get_data(conf_node
, KEY_HANDLE_EXPIRE_FREQ
, RECDB_QSTRING
);
5178 str
= database_get_data(conf_node
, KEY_ACCOUNT_EXPIRE_FREQ
, RECDB_QSTRING
);
5179 nickserv_conf
.handle_expire_frequency
= str
? ParseInterval(str
) : 86400;
5180 str
= database_get_data(conf_node
, KEY_HANDLE_EXPIRE_DELAY
, RECDB_QSTRING
);
5182 str
= database_get_data(conf_node
, KEY_ACCOUNT_EXPIRE_DELAY
, RECDB_QSTRING
);
5183 nickserv_conf
.handle_expire_delay
= str
? ParseInterval(str
) : 86400*30;
5184 str
= database_get_data(conf_node
, KEY_NOCHAN_HANDLE_EXPIRE_DELAY
, RECDB_QSTRING
);
5186 str
= database_get_data(conf_node
, KEY_NOCHAN_ACCOUNT_EXPIRE_DELAY
, RECDB_QSTRING
);
5187 nickserv_conf
.nochan_handle_expire_delay
= str
? ParseInterval(str
) : 86400*15;
5188 str
= database_get_data(conf_node
, "warn_clone_auth", RECDB_QSTRING
);
5189 nickserv_conf
.warn_clone_auth
= str
? !disabled_string(str
) : 1;
5190 str
= database_get_data(conf_node
, "default_maxlogins", RECDB_QSTRING
);
5191 nickserv_conf
.default_maxlogins
= str
? strtoul(str
, NULL
, 0) : 2;
5192 str
= database_get_data(conf_node
, "hard_maxlogins", RECDB_QSTRING
);
5193 nickserv_conf
.hard_maxlogins
= str
? strtoul(str
, NULL
, 0) : 10;
5194 str
= database_get_data(conf_node
, KEY_OUNREGISTER_INACTIVE
, RECDB_QSTRING
);
5195 nickserv_conf
.ounregister_inactive
= str
? ParseInterval(str
) : 86400*28;
5196 str
= database_get_data(conf_node
, KEY_OUNREGISTER_FLAGS
, RECDB_QSTRING
);
5199 nickserv_conf
.ounregister_flags
= 0;
5201 unsigned int pos
= handle_inverse_flags
[(unsigned char)*str
];
5204 nickserv_conf
.ounregister_flags
|= 1 << (pos
- 1);
5206 if (!nickserv_conf
.disable_nicks
) {
5207 str
= database_get_data(conf_node
, "reclaim_action", RECDB_QSTRING
);
5208 nickserv_conf
.reclaim_action
= str
? reclaim_action_from_string(str
) : RECLAIM_NONE
;
5209 str
= database_get_data(conf_node
, "warn_nick_owned", RECDB_QSTRING
);
5210 nickserv_conf
.warn_nick_owned
= str
? enabled_string(str
) : 0;
5211 str
= database_get_data(conf_node
, "auto_reclaim_action", RECDB_QSTRING
);
5212 nickserv_conf
.auto_reclaim_action
= str
? reclaim_action_from_string(str
) : RECLAIM_NONE
;
5213 str
= database_get_data(conf_node
, "auto_reclaim_delay", RECDB_QSTRING
);
5214 nickserv_conf
.auto_reclaim_delay
= str
? ParseInterval(str
) : 0;
5215 str
= database_get_data(conf_node
, KEY_NICK_EXPIRE_FREQ
, RECDB_QSTRING
);
5216 nickserv_conf
.nick_expire_frequency
= str
? ParseInterval(str
) : 86400;
5217 str
= database_get_data(conf_node
, KEY_NICK_EXPIRE_DELAY
, RECDB_QSTRING
);
5218 nickserv_conf
.nick_expire_delay
= str
? ParseInterval(str
) : 86400*30;
5219 str
= database_get_data(conf_node
, "expire_nicks", RECDB_QSTRING
);
5220 nickserv_conf
.expire_nicks
= str
? enabled_string(str
) : 0;
5222 child
= database_get_data(conf_node
, KEY_FLAG_LEVELS
, RECDB_OBJECT
);
5223 for (it
=dict_first(child
); it
; it
=iter_next(it
)) {
5224 const char *key
= iter_key(it
), *value
;
5228 if (!strncasecmp(key
, "uc_", 3))
5229 flag
= toupper(key
[3]);
5230 else if (!strncasecmp(key
, "lc_", 3))
5231 flag
= tolower(key
[3]);
5235 if ((pos
= handle_inverse_flags
[flag
])) {
5236 value
= GET_RECORD_QSTRING((struct record_data
*)iter_data(it
));
5237 flag_access_levels
[pos
- 1] = strtoul(value
, NULL
, 0);
5240 if (nickserv_conf
.weak_password_dict
)
5241 dict_delete(nickserv_conf
.weak_password_dict
);
5242 nickserv_conf
.weak_password_dict
= dict_new();
5243 dict_set_free_keys(nickserv_conf
.weak_password_dict
, free
);
5244 dict_insert(nickserv_conf
.weak_password_dict
, strdup("password"), NULL
);
5245 dict_insert(nickserv_conf
.weak_password_dict
, strdup("<password>"), NULL
);
5246 str
= database_get_data(conf_node
, KEY_DICT_FILE
, RECDB_QSTRING
);
5248 nickserv_load_dict(str
);
5249 str
= database_get_data(conf_node
, KEY_NICK
, RECDB_QSTRING
);
5250 if (nickserv
&& str
)
5251 NickChange(nickserv
, str
, 0);
5252 str
= database_get_data(conf_node
, KEY_AUTOGAG_ENABLED
, RECDB_QSTRING
);
5253 nickserv_conf
.autogag_enabled
= str
? strtoul(str
, NULL
, 0) : 1;
5254 str
= database_get_data(conf_node
, KEY_AUTOGAG_DURATION
, RECDB_QSTRING
);
5255 nickserv_conf
.autogag_duration
= str
? ParseInterval(str
) : 1800;
5256 str
= database_get_data(conf_node
, KEY_EMAIL_VISIBLE_LEVEL
, RECDB_QSTRING
);
5257 nickserv_conf
.email_visible_level
= str
? strtoul(str
, NULL
, 0) : 800;
5258 str
= database_get_data(conf_node
, KEY_EMAIL_ENABLED
, RECDB_QSTRING
);
5259 nickserv_conf
.email_enabled
= str
? enabled_string(str
) : 0;
5260 str
= database_get_data(conf_node
, KEY_SYNC_LOG
, RECDB_QSTRING
);
5261 nickserv_conf
.sync_log
= str
? enabled_string(str
) : 0;
5262 str
= database_get_data(conf_node
, KEY_COOKIE_TIMEOUT
, RECDB_QSTRING
);
5263 nickserv_conf
.cookie_timeout
= str
? ParseInterval(str
) : 24*3600;
5264 str
= database_get_data(conf_node
, KEY_EMAIL_REQUIRED
, RECDB_QSTRING
);
5265 nickserv_conf
.email_required
= (nickserv_conf
.email_enabled
&& str
) ? enabled_string(str
) : 0;
5266 str
= database_get_data(conf_node
, KEY_ACCOUNTS_PER_EMAIL
, RECDB_QSTRING
);
5267 nickserv_conf
.handles_per_email
= str
? strtoul(str
, NULL
, 0) : 1;
5268 str
= database_get_data(conf_node
, KEY_EMAIL_SEARCH_LEVEL
, RECDB_QSTRING
);
5269 nickserv_conf
.email_search_level
= str
? strtoul(str
, NULL
, 0) : 600;
5270 str
= database_get_data(conf_node
, KEY_TITLEHOST_SUFFIX
, RECDB_QSTRING
);
5271 nickserv_conf
.titlehost_suffix
= str
? str
: "example.net";
5273 free_string_list(nickserv_conf
.denied_fakehost_words
);
5274 strlist
= database_get_data(conf_node
, KEY_DENIED_FAKEHOST_WORDS
, RECDB_STRING_LIST
);
5276 strlist
= string_list_copy(strlist
);
5278 strlist
= alloc_string_list(4);
5279 string_list_append(strlist
, strdup("sex"));
5280 string_list_append(strlist
, strdup("fuck"));
5282 nickserv_conf
.denied_fakehost_words
= strlist
;
5284 str
= database_get_data(conf_node
, KEY_DEFAULT_STYLE
, RECDB_QSTRING
);
5285 nickserv_conf
.default_style
= str
? str
[0] : HI_DEFAULT_STYLE
;
5287 str
= database_get_data(conf_node
, KEY_AUTO_OPER
, RECDB_QSTRING
);
5288 nickserv_conf
.auto_oper
= str
? str
: "";
5290 str
= database_get_data(conf_node
, KEY_AUTO_ADMIN
, RECDB_QSTRING
);
5291 nickserv_conf
.auto_admin
= str
? str
: "";
5293 str
= database_get_data(conf_node
, KEY_AUTO_OPER_PRIVS
, RECDB_QSTRING
);
5294 nickserv_conf
.auto_oper_privs
= str
? str
: "";
5296 str
= database_get_data(conf_node
, KEY_AUTO_ADMIN_PRIVS
, RECDB_QSTRING
);
5297 nickserv_conf
.auto_admin_privs
= str
? str
: "";
5299 str
= conf_get_data("server/network", RECDB_QSTRING
);
5300 nickserv_conf
.network_name
= str
? str
: "some IRC network";
5301 if (!nickserv_conf
.auth_policer_params
) {
5302 nickserv_conf
.auth_policer_params
= policer_params_new();
5303 policer_params_set(nickserv_conf
.auth_policer_params
, "size", "5");
5304 policer_params_set(nickserv_conf
.auth_policer_params
, "drain-rate", "0.05");
5306 child
= database_get_data(conf_node
, KEY_AUTH_POLICER
, RECDB_OBJECT
);
5307 for (it
=dict_first(child
); it
; it
=iter_next(it
))
5308 set_policer_param(iter_key(it
), iter_data(it
), nickserv_conf
.auth_policer_params
);
5310 str
= database_get_data(conf_node
, KEY_LDAP_ENABLE
, RECDB_QSTRING
);
5311 nickserv_conf
.ldap_enable
= str
? strtoul(str
, NULL
, 0) : 0;
5313 str
= database_get_data(conf_node
, KEY_FORCE_HANDLES_LOWERCASE
, RECDB_QSTRING
);
5314 nickserv_conf
.force_handles_lowercase
= str
? strtol(str
, NULL
, 0) : 0;
5317 if(nickserv_conf
.ldap_enable
> 0) {
5318 /* ldap is enabled but not compiled in - error out */
5319 log_module(MAIN_LOG
, LOG_ERROR
, "ldap is enabled in config, but not compiled in!");
5320 nickserv_conf
.ldap_enable
= 0;
5326 str
= database_get_data(conf_node
, KEY_LDAP_URI
, RECDB_QSTRING
);
5327 nickserv_conf
.ldap_uri
= str
? str
: "";
5329 str
= database_get_data(conf_node
, KEY_LDAP_BASE
, RECDB_QSTRING
);
5330 nickserv_conf
.ldap_base
= str
? str
: "";
5332 str
= database_get_data(conf_node
, KEY_LDAP_DN_FMT
, RECDB_QSTRING
);
5333 nickserv_conf
.ldap_dn_fmt
= str
? str
: "";
5335 str
= database_get_data(conf_node
, KEY_LDAP_VERSION
, RECDB_QSTRING
);
5336 nickserv_conf
.ldap_version
= str
? strtoul(str
, NULL
, 0) : 3;
5338 str
= database_get_data(conf_node
, KEY_LDAP_AUTOCREATE
, RECDB_QSTRING
);
5339 nickserv_conf
.ldap_autocreate
= str
? strtoul(str
, NULL
, 0) : 0;
5341 str
= database_get_data(conf_node
, KEY_LDAP_TIMEOUT
, RECDB_QSTRING
);
5342 nickserv_conf
.ldap_timeout
= str
? strtoul(str
, NULL
, 0) : 5;
5344 str
= database_get_data(conf_node
, KEY_LDAP_ADMIN_DN
, RECDB_QSTRING
);
5345 nickserv_conf
.ldap_admin_dn
= str
? str
: "";
5347 str
= database_get_data(conf_node
, KEY_LDAP_ADMIN_PASS
, RECDB_QSTRING
);
5348 nickserv_conf
.ldap_admin_pass
= str
? str
: "";
5350 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_ACCOUNT
, RECDB_QSTRING
);
5351 nickserv_conf
.ldap_field_account
= str
? str
: "";
5353 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_PASSWORD
, RECDB_QSTRING
);
5354 nickserv_conf
.ldap_field_password
= str
? str
: "";
5356 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_EMAIL
, RECDB_QSTRING
);
5357 nickserv_conf
.ldap_field_email
= str
? str
: "";
5359 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_OSLEVEL
, RECDB_QSTRING
);
5360 nickserv_conf
.ldap_field_oslevel
= str
? str
: "";
5362 str
= database_get_data(conf_node
, KEY_LDAP_OPER_GROUP_DN
, RECDB_QSTRING
);
5363 nickserv_conf
.ldap_oper_group_dn
= str
? str
: "";
5365 str
= database_get_data(conf_node
, KEY_LDAP_OPER_GROUP_LEVEL
, RECDB_QSTRING
);
5366 nickserv_conf
.ldap_oper_group_level
= str
? strtoul(str
, NULL
, 0) : 99;
5368 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_GROUP_MEMBER
, RECDB_QSTRING
);
5369 nickserv_conf
.ldap_field_group_member
= str
? str
: "";
5371 free_string_list(nickserv_conf
.ldap_object_classes
);
5372 strlist
= database_get_data(conf_node
, KEY_LDAP_OBJECT_CLASSES
, RECDB_STRING_LIST
);
5374 strlist
= string_list_copy(strlist
);
5376 strlist
= alloc_string_list(4);
5377 string_list_append(strlist
, strdup("top"));
5379 nickserv_conf
.ldap_object_classes
= strlist
;
5386 nickserv_reclaim(struct userNode
*user
, struct nick_info
*ni
, enum reclaim_action action
) {
5388 char newnick
[NICKLEN
+1];
5401 send_message(user
, nickserv
, "NSMSG_RECLAIM_WARN", ni
->nick
, ni
->owner
->handle
);
5402 send_message(user
, nickserv
, "NSMSG_RECLAIM_HOWTO", ni
->owner
->handle
, nickserv
->nick
, self
->name
, ni
->owner
->handle
);
5404 case RECLAIM_SVSNICK
:
5406 snprintf(newnick
, sizeof(newnick
), "Guest%d", rand()%10000
);
5407 } while (GetUserH(newnick
));
5408 irc_svsnick(nickserv
, user
, newnick
);
5411 msg
= user_find_message(user
, "NSMSG_RECLAIM_KILL");
5412 DelUser(user
, nickserv
, 1, msg
);
5418 nickserv_reclaim_p(void *data
) {
5419 struct userNode
*user
= data
;
5420 struct nick_info
*ni
= get_nick_info(user
->nick
);
5422 nickserv_reclaim(user
, ni
, nickserv_conf
.auto_reclaim_action
);
5426 check_user_nick(struct userNode
*user
, UNUSED_ARG(void *extra
)) {
5427 struct nick_info
*ni
;
5428 user
->modes
&= ~FLAGS_REGNICK
;
5429 if (!(ni
= get_nick_info(user
->nick
)))
5431 if (user
->handle_info
== ni
->owner
) {
5432 user
->modes
|= FLAGS_REGNICK
;
5436 if (nickserv_conf
.warn_nick_owned
)
5437 send_message(user
, nickserv
, "NSMSG_RECLAIM_WARN", ni
->nick
, ni
->owner
->handle
);
5438 send_message(user
, nickserv
, "NSMSG_RECLAIM_HOWTO", ni
->owner
->handle
, nickserv
->nick
, self
->name
, ni
->owner
->handle
);
5439 if (nickserv_conf
.auto_reclaim_action
== RECLAIM_NONE
)
5441 if (nickserv_conf
.auto_reclaim_delay
)
5442 timeq_add(now
+ nickserv_conf
.auto_reclaim_delay
, nickserv_reclaim_p
, user
);
5444 nickserv_reclaim(user
, ni
, nickserv_conf
.auto_reclaim_action
);
5450 handle_account(struct userNode
*user
, const char *stamp
)
5452 struct handle_info
*hi
;
5455 #ifdef WITH_PROTOCOL_P10
5456 time_t timestamp
= 0;
5458 colon
= strchr(stamp
, ':');
5459 if(colon
&& colon
[1])
5462 timestamp
= atoi(colon
+1);
5464 hi
= dict_find(nickserv_handle_dict
, stamp
, NULL
);
5465 if(hi
&& timestamp
&& hi
->registered
!= timestamp
)
5467 log_module(MAIN_LOG
, LOG_WARNING
, "%s using account %s but timestamp does not match %s is not %s.", user
->nick
, stamp
, ctime(×tamp
),
5468 ctime(&hi
->registered
));
5472 hi
= dict_find(nickserv_id_dict
, stamp
, NULL
);
5473 log_module(MAIN_LOG
, LOG_WARNING
, "Using non-P10 code in accounts, not tested at all!");
5477 if(!hi
&& nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_autocreate
&&
5478 (ldap_user_exists(stamp
) == LDAP_SUCCESS
)) {
5484 /* First attempt to get the email address from LDAP */
5485 if((rc
= ldap_get_user_info(stamp
, &email
) != LDAP_SUCCESS
))
5486 if(nickserv_conf
.email_required
)
5489 /* Now try to register the handle */
5490 if (cont
&& (hi
= nickserv_register(user
, user
, stamp
, NULL
, 1))) {
5491 if(nickserv_conf
.default_hostmask
)
5494 mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
5497 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
5498 string_list_append(hi
->masks
, mask_canonicalized
);
5502 nickserv_set_email_addr(hi
, email
);
5510 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
5513 set_user_handle_info(user
, hi
, 0);
5515 log_module(MAIN_LOG
, LOG_WARNING
, "%s had unknown account stamp %s.", user
->nick
, stamp
);
5520 handle_nick_change(struct userNode
*user
, const char *old_nick
, UNUSED_ARG(void *extra
))
5522 struct handle_info
*hi
;
5524 if ((hi
= dict_find(nickserv_allow_auth_dict
, old_nick
, 0))) {
5525 dict_remove(nickserv_allow_auth_dict
, old_nick
);
5526 dict_insert(nickserv_allow_auth_dict
, user
->nick
, hi
);
5528 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
5529 check_user_nick(user
, NULL
);
5533 nickserv_remove_user(struct userNode
*user
, UNUSED_ARG(struct userNode
*killer
), UNUSED_ARG(const char *why
), UNUSED_ARG(void *extra
))
5535 dict_remove(nickserv_allow_auth_dict
, user
->nick
);
5536 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
5537 set_user_handle_info(user
, NULL
, 0);
5540 static struct modcmd
*
5541 nickserv_define_func(const char *name
, modcmd_func_t func
, int min_level
, int must_auth
, int must_be_qualified
)
5543 if (min_level
> 0) {
5545 sprintf(buf
, "%u", min_level
);
5546 if (must_be_qualified
) {
5547 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "level", buf
, "flags", "+qualified,+loghostmask", NULL
);
5549 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "level", buf
, NULL
);
5551 } else if (min_level
== 0) {
5552 if (must_be_qualified
) {
5553 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+helping", NULL
);
5555 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+helping", NULL
);
5558 if (must_be_qualified
) {
5559 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+qualified,+loghostmask", NULL
);
5561 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), NULL
);
5566 #define SDFLAG_STALE 0x01 /**< SASL session data is stale, delete on next pass. */
5570 struct SASLSession
*next
;
5571 struct SASLSession
*prev
;
5572 struct server
* source
;
5582 struct SASLSession
*saslsessions
= NULL
;
5585 sasl_delete_session(struct SASLSession
*session
)
5592 session
->buf
= NULL
;
5594 if (session
->sslclifp
)
5595 free(session
->sslclifp
);
5596 session
->sslclifp
= NULL
;
5598 if (session
->hostmask
)
5599 free(session
->hostmask
);
5600 session
->hostmask
= NULL
;
5603 session
->next
->prev
= session
->prev
;
5605 session
->prev
->next
= session
->next
;
5607 saslsessions
= session
->next
;
5613 sasl_delete_stale(UNUSED_ARG(void *data
))
5617 struct SASLSession
*sess
= NULL
;
5618 struct SASLSession
*nextsess
= NULL
;
5620 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Checking for stale sessions");
5622 for (sess
= saslsessions
; sess
; sess
= nextsess
)
5624 nextsess
= sess
->next
;
5626 if (sess
->flags
& SDFLAG_STALE
)
5629 sasl_delete_session(sess
);
5634 sess
->flags
|= SDFLAG_STALE
;
5639 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Deleted %d stale sessions, %d remaining", delcount
, remcount
);
5641 timeq_add(now
+ 30, sasl_delete_stale
, NULL
);
5645 sasl_get_session(const char *uid
)
5647 struct SASLSession
*sess
;
5649 for (sess
= saslsessions
; sess
; sess
= sess
->next
)
5651 if (!strncmp(sess
->uid
, uid
, 128))
5653 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Found session for %s", sess
->uid
);
5658 sess
= malloc(sizeof(struct SASLSession
));
5659 memset(sess
, 0, sizeof(struct SASLSession
));
5661 strncpy(sess
->uid
, uid
, 128);
5664 timeq_add(now
+ 30, sasl_delete_stale
, NULL
);
5667 saslsessions
->prev
= sess
;
5668 sess
->next
= saslsessions
;
5669 saslsessions
= sess
;
5671 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Created session for %s", sess
->uid
);
5676 sasl_packet(struct SASLSession
*session
)
5678 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Got packet containing: %s", session
->buf
);
5680 if (!session
->mech
[0])
5682 log_module(NS_LOG
, LOG_DEBUG
, "SASL: No mechanism stored yet, using %s", session
->buf
);
5683 if (strcmp(session
->buf
, "PLAIN") && (strcmp(session
->buf
, "EXTERNAL") || !session
->sslclifp
)) {
5684 if (!session
->sslclifp
)
5685 irc_sasl(session
->source
, session
->uid
, "M", "PLAIN");
5687 irc_sasl(session
->source
, session
->uid
, "M", "PLAIN,EXTERNAL");
5688 irc_sasl(session
->source
, session
->uid
, "D", "F");
5689 sasl_delete_session(session
);
5693 strncpy(session
->mech
, session
->buf
, 10);
5694 irc_sasl(session
->source
, session
->uid
, "C", "+");
5696 else if (!strcmp(session
->mech
, "EXTERNAL"))
5700 char *authzid
= NULL
;
5701 struct handle_info
*hi
= NULL
;
5702 static char buffer
[256];
5704 base64_decode_alloc(session
->buf
, session
->buflen
, &raw
, &rawlen
);
5709 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Checking supplied credentials");
5711 if (!session
->sslclifp
) {
5712 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Incomplete credentials supplied");
5713 irc_sasl(session
->source
, session
->uid
, "D", "F");
5715 if (!(hi
= loc_auth(session
->sslclifp
, authzid
, NULL
, session
->hostmask
)))
5717 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Invalid credentials supplied");
5718 irc_sasl(session
->source
, session
->uid
, "D", "F");
5722 snprintf(buffer
, sizeof(buffer
), "%s "FMT_TIME_T
, hi
->handle
, hi
->registered
);
5723 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Valid credentials supplied");
5724 irc_sasl(session
->source
, session
->uid
, "L", buffer
);
5725 irc_sasl(session
->source
, session
->uid
, "D", "S");
5729 sasl_delete_session(session
);
5734 else /* We only have PLAIN at the moment so next message must be credentials */
5738 char *authzid
= NULL
;
5739 char *authcid
= NULL
;
5740 char *passwd
= NULL
;
5742 unsigned int i
= 0, c
= 0;
5743 struct handle_info
*hi
= NULL
;
5744 static char buffer
[256];
5746 base64_decode_alloc(session
->buf
, session
->buflen
, &raw
, &rawlen
);
5748 raw
= (char *)realloc(raw
, rawlen
+1);
5753 for (i
=0; i
<rawlen
; i
++)
5764 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Checking supplied credentials");
5768 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Incomplete credentials supplied");
5769 irc_sasl(session
->source
, session
->uid
, "D", "F");
5773 if (!(hi
= loc_auth(session
->sslclifp
, authcid
, passwd
, session
->hostmask
)))
5775 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Invalid credentials supplied");
5776 irc_sasl(session
->source
, session
->uid
, "D", "F");
5780 snprintf(buffer
, sizeof(buffer
), "%s "FMT_TIME_T
, hi
->handle
, hi
->registered
);
5781 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Valid credentials supplied");
5782 irc_sasl(session
->source
, session
->uid
, "L", buffer
);
5783 irc_sasl(session
->source
, session
->uid
, "D", "S");
5787 sasl_delete_session(session
);
5793 /* clear stale state */
5794 session
->flags
&= ~SDFLAG_STALE
;
5798 handle_sasl_input(struct server
* source
,const char *uid
, const char *subcmd
, const char *data
, const char *ext
, UNUSED_ARG(void *extra
))
5800 struct SASLSession
* sess
= sasl_get_session(uid
);
5801 int len
= strlen(data
);
5803 sess
->source
= source
;
5805 if (!strcmp(subcmd
, "D"))
5807 sasl_delete_session(sess
);
5811 if (!strcmp(subcmd
, "H")) {
5812 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Storing host mask %s", data
);
5813 sess
->hostmask
= strdup(data
);
5817 if (strcmp(subcmd
, "S") && strcmp(subcmd
, "C"))
5823 if (sess
->p
== NULL
)
5825 sess
->buf
= (char *)malloc(len
+ 1);
5826 sess
->p
= sess
->buf
;
5831 if (sess
->buflen
+ len
+ 1 > 8192) /* This is a little much... */
5833 irc_sasl(source
, uid
, "D", "F");
5834 sasl_delete_session(sess
);
5838 sess
->buf
= (char *)realloc(sess
->buf
, sess
->buflen
+ len
+ 1);
5839 sess
->p
= sess
->buf
+ sess
->buflen
;
5840 sess
->buflen
+= len
;
5843 memcpy(sess
->p
, data
, len
);
5844 sess
->buf
[len
] = '\0';
5847 sess
->sslclifp
= strdup(ext
);
5849 /* Messages not exactly 400 bytes are the end of a packet. */
5854 if (sess
->buf
!= NULL
)
5856 sess
->buf
= sess
->p
= NULL
;
5861 nickserv_db_cleanup(UNUSED_ARG(void* extra
))
5863 unreg_del_user_func(nickserv_remove_user
, NULL
);
5864 unreg_sasl_input_func(handle_sasl_input
, NULL
);
5865 userList_clean(&curr_helpers
);
5866 policer_params_delete(nickserv_conf
.auth_policer_params
);
5867 dict_delete(nickserv_handle_dict
);
5868 dict_delete(nickserv_nick_dict
);
5869 dict_delete(nickserv_opt_dict
);
5870 dict_delete(nickserv_allow_auth_dict
);
5871 dict_delete(nickserv_email_dict
);
5872 dict_delete(nickserv_id_dict
);
5873 dict_delete(nickserv_conf
.weak_password_dict
);
5874 free(auth_func_list
);
5875 free(auth_func_list_extra
);
5876 free(unreg_func_list
);
5877 free(unreg_func_list_extra
);
5879 free(rf_list_extra
);
5880 free(allowauth_func_list
);
5881 free(allowauth_func_list_extra
);
5882 free(handle_merge_func_list
);
5883 free(handle_merge_func_list_extra
);
5884 free(failpw_func_list
);
5885 free(failpw_func_list_extra
);
5886 if (nickserv_conf
.valid_handle_regex_set
)
5887 regfree(&nickserv_conf
.valid_handle_regex
);
5888 if (nickserv_conf
.valid_nick_regex_set
)
5889 regfree(&nickserv_conf
.valid_nick_regex
);
5892 void handle_loc_auth_oper(struct userNode
*user
, UNUSED_ARG(struct handle_info
*old_handle
), UNUSED_ARG(void *extra
)) {
5893 char *privv
[MAXNUMPARAMS
];
5896 if (!*nickserv_conf
.auto_oper
|| !user
->handle_info
)
5899 if (!IsOper(user
)) {
5900 if (*nickserv_conf
.auto_admin
&& user
->handle_info
->opserv_level
>= opserv_conf_admin_level()) {
5901 if (nickserv_conf
.auto_admin_privs
[0]) {
5902 irc_raw_privs(user
, nickserv_conf
.auto_admin_privs
);
5903 privc
= split_line(strdup(nickserv_conf
.auto_admin_privs
), false, MAXNUMPARAMS
, privv
);
5904 for (i
= 0; i
< privc
; i
++) {
5905 client_modify_priv_by_name(user
, privv
[i
], 1);
5908 irc_umode(user
, nickserv_conf
.auto_admin
);
5909 irc_sno(0x1, "%s (%s@%s) is now an IRC Administrator",
5910 user
->nick
, user
->ident
, user
->hostname
);
5911 send_message(user
, nickserv
, "NSMSG_AUTO_OPER_ADMIN");
5912 } else if (*nickserv_conf
.auto_oper
&& user
->handle_info
->opserv_level
) {
5913 if (nickserv_conf
.auto_oper_privs
[0]) {
5914 irc_raw_privs(user
, nickserv_conf
.auto_oper_privs
);
5915 privc
= split_line(strdup(nickserv_conf
.auto_oper_privs
), false, MAXNUMPARAMS
, privv
);
5916 for (i
= 0; i
< privc
; i
++) {
5917 client_modify_priv_by_name(user
, privv
[i
], 1);
5920 irc_umode(user
, nickserv_conf
.auto_oper
);
5921 irc_sno(0x1, "%s (%s@%s) is now an IRC Operator",
5922 user
->nick
, user
->ident
, user
->hostname
);
5923 send_message(user
, nickserv
, "NSMSG_AUTO_OPER");
5929 init_nickserv(const char *nick
)
5931 struct chanNode
*chan
;
5933 NS_LOG
= log_register_type("NickServ", "file:nickserv.log");
5934 reg_new_user_func(check_user_nick
, NULL
);
5935 reg_nick_change_func(handle_nick_change
, NULL
);
5936 reg_del_user_func(nickserv_remove_user
, NULL
);
5937 reg_account_func(handle_account
);
5938 reg_auth_func(handle_loc_auth_oper
, NULL
);
5939 reg_sasl_input_func(handle_sasl_input
, NULL
);
5941 /* set up handle_inverse_flags */
5942 memset(handle_inverse_flags
, 0, sizeof(handle_inverse_flags
));
5943 for (i
=0; handle_flags
[i
]; i
++) {
5944 handle_inverse_flags
[(unsigned char)handle_flags
[i
]] = i
+ 1;
5945 flag_access_levels
[i
] = 0;
5948 conf_register_reload(nickserv_conf_read
);
5949 nickserv_opt_dict
= dict_new();
5950 nickserv_email_dict
= dict_new();
5952 dict_set_free_keys(nickserv_email_dict
, free
);
5953 dict_set_free_data(nickserv_email_dict
, nickserv_free_email_addr
);
5955 nickserv_module
= module_register("NickServ", NS_LOG
, "nickserv.help", NULL
);
5956 /* Removed qualified_host as default requirement for AUTH, REGISTER, PASS, etc. nets
5957 * can enable it per command using modcmd. (its a shitty default IMO, and now in 1.3
5958 * a big pain to disable since its nolonger in the config file. ) -Rubin
5960 modcmd_register(nickserv_module
, "AUTH", cmd_auth
, 2, MODCMD_KEEP_BOUND
, "flags", "+loghostmask", NULL
);
5961 nickserv_define_func("ALLOWAUTH", cmd_allowauth
, 0, 1, 0);
5962 nickserv_define_func("REGISTER", cmd_register
, -1, 0, 0);
5963 nickserv_define_func("OREGISTER", cmd_oregister
, 0, 1, 0);
5964 nickserv_define_func("UNREGISTER", cmd_unregister
, -1, 1, 0);
5965 nickserv_define_func("OUNREGISTER", cmd_ounregister
, 0, 1, 0);
5966 nickserv_define_func("ADDMASK", cmd_addmask
, -1, 1, 0);
5967 nickserv_define_func("OADDMASK", cmd_oaddmask
, 0, 1, 0);
5968 nickserv_define_func("DELMASK", cmd_delmask
, -1, 1, 0);
5969 nickserv_define_func("ODELMASK", cmd_odelmask
, 0, 1, 0);
5970 nickserv_define_func("ADDSSLFP", cmd_addsslfp
, -1, 1, 0);
5971 nickserv_define_func("OADDSSLFP", cmd_oaddsslfp
, 0, 1, 0);
5972 nickserv_define_func("DELSSLFP", cmd_delsslfp
, -1, 1, 0);
5973 nickserv_define_func("ODELSSLFP", cmd_odelsslfp
, 0, 1, 0);
5974 nickserv_define_func("PASS", cmd_pass
, -1, 1, 0);
5975 nickserv_define_func("SET", cmd_set
, -1, 1, 0);
5976 nickserv_define_func("OSET", cmd_oset
, 0, 1, 0);
5977 nickserv_define_func("ACCOUNTINFO", cmd_handleinfo
, -1, 0, 0);
5978 nickserv_define_func("USERINFO", cmd_userinfo
, -1, 1, 0);
5979 nickserv_define_func("RENAME", cmd_rename_handle
, -1, 1, 0);
5980 nickserv_define_func("VACATION", cmd_vacation
, -1, 1, 0);
5981 nickserv_define_func("MERGE", cmd_merge
, 750, 1, 0);
5982 if (!nickserv_conf
.disable_nicks
) {
5983 /* nick management commands */
5984 nickserv_define_func("REGNICK", cmd_regnick
, -1, 1, 0);
5985 nickserv_define_func("OREGNICK", cmd_oregnick
, 0, 1, 0);
5986 nickserv_define_func("UNREGNICK", cmd_unregnick
, -1, 1, 0);
5987 nickserv_define_func("OUNREGNICK", cmd_ounregnick
, 0, 1, 0);
5988 nickserv_define_func("NICKINFO", cmd_nickinfo
, -1, 1, 0);
5989 nickserv_define_func("RECLAIM", cmd_reclaim
, -1, 1, 0);
5991 if (nickserv_conf
.email_enabled
) {
5992 nickserv_define_func("AUTHCOOKIE", cmd_authcookie
, -1, 0, 0);
5993 nickserv_define_func("RESETPASS", cmd_resetpass
, -1, 0, 0);
5994 nickserv_define_func("COOKIE", cmd_cookie
, -1, 0, 0);
5995 nickserv_define_func("DELCOOKIE", cmd_delcookie
, -1, 1, 0);
5996 nickserv_define_func("ODELCOOKIE", cmd_odelcookie
, 0, 1, 0);
5997 dict_insert(nickserv_opt_dict
, "EMAIL", opt_email
);
5999 nickserv_define_func("GHOST", cmd_ghost
, -1, 1, 0);
6000 /* ignore commands */
6001 nickserv_define_func("ADDIGNORE", cmd_addignore
, -1, 1, 0);
6002 nickserv_define_func("OADDIGNORE", cmd_oaddignore
, 0, 1, 0);
6003 nickserv_define_func("DELIGNORE", cmd_delignore
, -1, 1, 0);
6004 nickserv_define_func("ODELIGNORE", cmd_odelignore
, 0, 1, 0);
6005 /* miscellaneous commands */
6006 nickserv_define_func("STATUS", cmd_status
, -1, 0, 0);
6007 nickserv_define_func("SEARCH", cmd_search
, 100, 1, 0);
6008 nickserv_define_func("SEARCH UNREGISTER", NULL
, 800, 1, 0);
6009 nickserv_define_func("MERGEDB", cmd_mergedb
, 999, 1, 0);
6010 nickserv_define_func("CHECKPASS", cmd_checkpass
, 601, 1, 0);
6011 nickserv_define_func("CHECKEMAIL", cmd_checkemail
, 0, 1, 0);
6013 dict_insert(nickserv_opt_dict
, "INFO", opt_info
);
6014 dict_insert(nickserv_opt_dict
, "WIDTH", opt_width
);
6015 dict_insert(nickserv_opt_dict
, "TABLEWIDTH", opt_tablewidth
);
6016 dict_insert(nickserv_opt_dict
, "COLOR", opt_color
);
6017 dict_insert(nickserv_opt_dict
, "PRIVMSG", opt_privmsg
);
6018 dict_insert(nickserv_opt_dict
, "AUTOHIDE", opt_autohide
);
6019 dict_insert(nickserv_opt_dict
, "STYLE", opt_style
);
6020 dict_insert(nickserv_opt_dict
, "PASS", opt_password
);
6021 dict_insert(nickserv_opt_dict
, "PASSWORD", opt_password
);
6022 dict_insert(nickserv_opt_dict
, "FLAGS", opt_flags
);
6023 dict_insert(nickserv_opt_dict
, "ACCESS", opt_level
);
6024 dict_insert(nickserv_opt_dict
, "LEVEL", opt_level
);
6025 dict_insert(nickserv_opt_dict
, "EPITHET", opt_epithet
);
6026 dict_insert(nickserv_opt_dict
, "NOTE", opt_note
);
6027 if (nickserv_conf
.titlehost_suffix
) {
6028 dict_insert(nickserv_opt_dict
, "TITLE", opt_title
);
6029 dict_insert(nickserv_opt_dict
, "FAKEHOST", opt_fakehost
);
6031 dict_insert(nickserv_opt_dict
, "ANNOUNCEMENTS", opt_announcements
);
6032 dict_insert(nickserv_opt_dict
, "MAXLOGINS", opt_maxlogins
);
6033 dict_insert(nickserv_opt_dict
, "ADVANCED", opt_advanced
);
6034 dict_insert(nickserv_opt_dict
, "LANGUAGE", opt_language
);
6035 dict_insert(nickserv_opt_dict
, "KARMA", opt_karma
);
6037 nickserv_handle_dict
= dict_new();
6038 dict_set_free_keys(nickserv_handle_dict
, free
);
6039 dict_set_free_data(nickserv_handle_dict
, free_handle_info
);
6041 nickserv_id_dict
= dict_new();
6042 dict_set_free_keys(nickserv_id_dict
, free
);
6044 nickserv_nick_dict
= dict_new();
6045 dict_set_free_data(nickserv_nick_dict
, free
);
6047 nickserv_allow_auth_dict
= dict_new();
6049 userList_init(&curr_helpers
);
6052 const char *modes
= conf_get_data("services/nickserv/modes", RECDB_QSTRING
);
6053 nickserv
= AddLocalUser(nick
, nick
, NULL
, "Nick Services", modes
);
6054 nickserv_service
= service_register(nickserv
);
6056 saxdb_register("NickServ", nickserv_saxdb_read
, nickserv_saxdb_write
);
6057 reg_exit_func(nickserv_db_cleanup
, NULL
);
6058 if(nickserv_conf
.handle_expire_frequency
)
6059 timeq_add(now
+ nickserv_conf
.handle_expire_frequency
, expire_handles
, NULL
);
6060 if(nickserv_conf
.nick_expire_frequency
&& nickserv_conf
.expire_nicks
)
6061 timeq_add(now
+ nickserv_conf
.nick_expire_frequency
, expire_nicks
, NULL
);
6063 if(autojoin_channels
&& nickserv
) {
6064 for (i
= 0; i
< autojoin_channels
->used
; i
++) {
6065 chan
= AddChannel(autojoin_channels
->list
[i
], now
, "+nt", NULL
, NULL
);
6066 AddChannelUser(nickserv
, chan
)->modes
|= MODE_CHANOP
;
6071 ldap_do_init(nickserv_conf
);
6074 message_register_table(msgtab
);