1 /* nickserv.c - Nick/authentication service
2 * Copyright 2000-2004 srvx Development Team
4 * This file is part of x3.
6 * x3 is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with srvx; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 #include "opserv.h" /* for gag_create(), opserv_bad_channel() */
32 #include <tre/regex.h>
38 #define NICKSERV_CONF_NAME "services/nickserv"
40 #define KEY_DISABLE_NICKS "disable_nicks"
41 #define KEY_DEFAULT_HOSTMASK "default_hostmask"
42 #define KEY_NICKS_PER_HANDLE "nicks_per_handle"
43 #define KEY_NICKS_PER_ACCOUNT "nicks_per_account"
44 #define KEY_PASSWORD_MIN_LENGTH "password_min_length"
45 #define KEY_PASSWORD_MIN_DIGITS "password_min_digits"
46 #define KEY_PASSWORD_MIN_UPPER "password_min_upper"
47 #define KEY_PASSWORD_MIN_LOWER "password_min_lower"
48 #define KEY_VALID_HANDLE_REGEX "valid_handle_regex"
49 #define KEY_VALID_ACCOUNT_REGEX "valid_account_regex"
50 #define KEY_VALID_NICK_REGEX "valid_nick_regex"
51 #define KEY_VALID_FAKEHOST_REGEX "valid_fakehost_regex"
52 #define KEY_DB_BACKUP_FREQ "db_backup_freq"
53 #define KEY_MODOPER_LEVEL "modoper_level"
54 #define KEY_SET_EPITHET_LEVEL "set_epithet_level"
55 #define KEY_SET_TITLE_LEVEL "set_title_level"
56 #define KEY_SET_FAKEHOST_LEVEL "set_fakehost_level"
57 #define KEY_DENIED_FAKEHOST_WORDS "denied_fakehost_words"
58 #define KEY_TITLEHOST_SUFFIX "titlehost_suffix"
59 #define KEY_AUTO_OPER "auto_oper"
60 #define KEY_AUTO_ADMIN "auto_admin"
61 #define KEY_AUTO_OPER_PRIVS "auto_oper_privs"
62 #define KEY_AUTO_ADMIN_PRIVS "auto_admin_privs"
63 #define KEY_FLAG_LEVELS "flag_levels"
64 #define KEY_HANDLE_EXPIRE_FREQ "handle_expire_freq"
65 #define KEY_ACCOUNT_EXPIRE_FREQ "account_expire_freq"
66 #define KEY_HANDLE_EXPIRE_DELAY "handle_expire_delay"
67 #define KEY_ACCOUNT_EXPIRE_DELAY "account_expire_delay"
68 #define KEY_NOCHAN_HANDLE_EXPIRE_DELAY "nochan_handle_expire_delay"
69 #define KEY_NOCHAN_ACCOUNT_EXPIRE_DELAY "nochan_account_expire_delay"
70 #define KEY_DICT_FILE "dict_file"
71 #define KEY_NICK "nick"
72 #define KEY_LANGUAGE "language"
73 #define KEY_AUTOGAG_ENABLED "autogag_enabled"
74 #define KEY_AUTOGAG_DURATION "autogag_duration"
75 #define KEY_AUTH_POLICER "auth_policer"
76 #define KEY_EMAIL_VISIBLE_LEVEL "email_visible_level"
77 #define KEY_EMAIL_ENABLED "email_enabled"
78 #define KEY_EMAIL_REQUIRED "email_required"
79 #define KEY_SYNC_LOG "sync_log"
80 #define KEY_COOKIE_TIMEOUT "cookie_timeout"
81 #define KEY_ACCOUNTS_PER_EMAIL "accounts_per_email"
82 #define KEY_EMAIL_SEARCH_LEVEL "email_search_level"
83 #define KEY_DEFAULT_STYLE "default_style"
84 #define KEY_OUNREGISTER_INACTIVE "ounregister_inactive"
85 #define KEY_OUNREGISTER_FLAGS "ounregister_flags"
88 #define KEY_PASSWD "passwd"
89 #define KEY_NICKS "nicks"
90 #define KEY_MASKS "masks"
91 #define KEY_SSLFPS "sslfps"
92 #define KEY_IGNORES "ignores"
93 #define KEY_OPSERV_LEVEL "opserv_level"
94 #define KEY_FLAGS "flags"
95 #define KEY_REGISTER_ON "register"
96 #define KEY_LAST_SEEN "lastseen"
97 #define KEY_INFO "info"
98 #define KEY_USERLIST_STYLE "user_style"
99 #define KEY_SCREEN_WIDTH "screen_width"
100 #define KEY_LAST_AUTHED_HOST "last_authed_host"
101 #define KEY_LAST_QUIT_HOST "last_quit_host"
102 #define KEY_EMAIL_ADDR "email_addr"
103 #define KEY_COOKIE "cookie"
104 #define KEY_COOKIE_DATA "data"
105 #define KEY_COOKIE_TYPE "type"
106 #define KEY_COOKIE_EXPIRES "expires"
107 #define KEY_ACTIVATION "activation"
108 #define KEY_PASSWORD_CHANGE "password change"
109 #define KEY_EMAIL_CHANGE "email change"
110 #define KEY_ALLOWAUTH "allowauth"
111 #define KEY_EPITHET "epithet"
112 #define KEY_TABLE_WIDTH "table_width"
113 #define KEY_ANNOUNCEMENTS "announcements"
114 #define KEY_MAXLOGINS "maxlogins"
115 #define KEY_FAKEHOST "fakehost"
116 #define KEY_NOTE_NOTE "note"
117 #define KEY_NOTE_SETTER "setter"
118 #define KEY_NOTE_DATE "date"
119 #define KEY_KARMA "karma"
120 #define KEY_FORCE_HANDLES_LOWERCASE "force_handles_lowercase"
122 #define KEY_LDAP_ENABLE "ldap_enable"
125 #define KEY_LDAP_URI "ldap_uri"
126 #define KEY_LDAP_BASE "ldap_base"
127 #define KEY_LDAP_DN_FMT "ldap_dn_fmt"
128 #define KEY_LDAP_VERSION "ldap_version"
129 #define KEY_LDAP_AUTOCREATE "ldap_autocreate"
130 #define KEY_LDAP_ADMIN_DN "ldap_admin_dn"
131 #define KEY_LDAP_ADMIN_PASS "ldap_admin_pass"
132 #define KEY_LDAP_FIELD_ACCOUNT "ldap_field_account"
133 #define KEY_LDAP_FIELD_PASSWORD "ldap_field_password"
134 #define KEY_LDAP_FIELD_EMAIL "ldap_field_email"
135 #define KEY_LDAP_FIELD_OSLEVEL "ldap_field_oslevel"
136 #define KEY_LDAP_OBJECT_CLASSES "ldap_object_classes"
137 #define KEY_LDAP_OPER_GROUP_DN "ldap_oper_group_dn"
138 #define KEY_LDAP_OPER_GROUP_LEVEL "ldap_oper_group_level"
139 #define KEY_LDAP_FIELD_GROUP_MEMBER "ldap_field_group_member"
140 #define KEY_LDAP_TIMEOUT "ldap_timeout"
143 #define NICKSERV_VALID_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
145 #define NICKSERV_FUNC(NAME) MODCMD_FUNC(NAME)
146 #define OPTION_FUNC(NAME) int NAME(UNUSED_ARG(struct svccmd *cmd), struct userNode *user, struct handle_info *hi, UNUSED_ARG(unsigned int override), unsigned int argc, char *argv[])
147 typedef OPTION_FUNC(option_func_t
);
149 DEFINE_LIST(handle_info_list
, struct handle_info
*)
151 #define NICKSERV_MIN_PARMS(N) do { \
153 reply("MSG_MISSING_PARAMS", argv[0]); \
154 svccmd_send_help_brief(user, nickserv, cmd); \
158 struct userNode
*nickserv
;
159 struct userList curr_helpers
;
160 const char *handle_flags
= HANDLE_FLAGS
;
162 extern struct string_list
*autojoin_channels
;
163 static struct module *nickserv_module
;
164 static struct service
*nickserv_service
;
165 static struct log_type
*NS_LOG
;
166 dict_t nickserv_handle_dict
; /* contains struct handle_info* */
167 static dict_t nickserv_id_dict
; /* contains struct handle_info* */
168 static dict_t nickserv_nick_dict
; /* contains struct nick_info* */
169 static dict_t nickserv_opt_dict
; /* contains option_func_t* */
170 static dict_t nickserv_allow_auth_dict
; /* contains struct handle_info* */
171 static dict_t nickserv_email_dict
; /* contains struct handle_info_list*, indexed by email addr */
172 static char handle_inverse_flags
[256];
173 static unsigned int flag_access_levels
[32];
174 static const struct message_entry msgtab
[] = {
175 { "NSMSG_NO_ANGLEBRACKETS", "The < and > in help indicate that that word is a required parameter, but DO NOT actually type them in messages to me." },
176 { "NSMSG_HANDLE_EXISTS", "Account $b%s$b is already registered." },
177 { "NSMSG_HANDLE_TOLONG", "The account name %s is too long. Account names must be %lu characters or less."},
178 { "NSMSG_PASSWORD_SHORT", "Your password must be at least %lu characters long." },
179 { "NSMSG_PASSWORD_ACCOUNT", "Your password may not be the same as your account name." },
180 { "NSMSG_PASSWORD_DICTIONARY", "Your password is too simple. You must choose a password that is not just a word or name." },
181 { "NSMSG_PASSWORD_READABLE", "Your password must have at least %lu digit(s), %lu capital letter(s), and %lu lower-case letter(s)." },
182 { "NSMSG_LDAP_FAIL", "There was a problem in contacting the account server (ldap): %s. Please try again later." },
183 { "NSMSG_LDAP_FAIL_ADD", "There was a problem in adding account %s to ldap: %s." },
184 { "NSMSG_LDAP_FAIL_SEND_EMAIL", "There was a problem in storing your email address in the account server (ldap): %s. Please try again later." },
185 { "NSMSG_LDAP_FAIL_GET_EMAIL", "There was a problem in retrieving your email address from the account server (ldap): %s. Please try again later." },
186 { "NSMSG_PARTIAL_REGISTER", "Account has been registered to you; nick was already registered to someone else." },
187 { "NSMSG_OREGISTER_VICTIM", "%s has registered a new account for you (named %s)." },
188 { "NSMSG_OREGISTER_H_SUCCESS", "Account has been registered." },
189 { "NSMSG_REGISTER_H_SUCCESS", "Account has been registered to you." },
190 { "NSMSG_REGISTER_HN_SUCCESS", "Account and nick have been registered to you." },
191 { "NSMSG_REQUIRE_OPER", "You must be an $bIRC Operator$b to register the first account." },
192 { "NSMSG_ROOT_HANDLE", "Account %s has been granted $broot-level privileges$b." },
193 { "NSMSG_USE_COOKIE_REGISTER", "To activate your account, you must check your email for the \"cookie\" that has been mailed to it. When you have it, use the $bcookie$b command to complete registration." },
194 { "NSMSG_USE_COOKIE_RESETPASS", "A cookie has been mailed to your account's email address. You must check your email and use the $bcookie$b command to confirm the password change." },
195 { "NSMSG_USE_COOKIE_EMAIL_1", "A cookie has been mailed to the new address you requested. To finish setting your email address, please check your email for the cookie and use the $bcookie$b command to verify." },
196 { "NSMSG_USE_COOKIE_EMAIL_2", "A cookie has been generated, and half mailed to each your old and new addresses. To finish changing your email address, please check your email for the cookie and use the $bcookie$b command to verify." },
197 { "NSMSG_USE_COOKIE_AUTH", "A cookie has been generated and sent to your email address. Once you have checked your email and received the cookie, auth using the $bcookie$b command." },
198 { "NSMSG_COOKIE_LIVE", "Account $b%s$b already has a cookie active. Please either finish using that cookie, wait for it to expire, or auth to the account and use the $bdelcookie$b command." },
199 { "NSMSG_EMAIL_UNACTIVATED", "That email address already has an unused cookie outstanding. Please use the cookie or wait for it to expire." },
200 { "NSMSG_NO_COOKIE", "Your account does not have any cookie issued right now." },
201 { "NSMSG_NO_COOKIE_FOREIGN", "The account $b%s$b does not have any cookie issued right now." },
202 { "NSMSG_CANNOT_COOKIE", "You cannot use that kind of cookie when you are logged in." },
203 { "NSMSG_BAD_COOKIE", "That cookie is not the right one. Please make sure you are copying it EXACTLY from the email; it is case-sensitive, so $bABC$b is different from $babc$b." },
204 { "NSMSG_HANDLE_ACTIVATED", "Your account is now activated (with the password you entered when you registered). You are now authenticated to your account." },
205 { "NSMSG_PASSWORD_CHANGED", "You have successfully changed your password to what you requested with the $bresetpass$b command." },
206 { "NSMSG_EMAIL_PROHIBITED", "%s may not be used as an email address: %s" },
207 { "NSMSG_EMAIL_OVERUSED", "That email address already has an account. Use RESETPASS if you forgot your password." },
208 { "NSMSG_EMAIL_SAME", "That is the email address already there; no need to change it." },
209 { "NSMSG_EMAIL_CHANGED", "You have successfully changed your email address." },
210 { "NSMSG_BAD_COOKIE_TYPE", "Your account had bad cookie type %d; sorry. I am confused. Please report this bug." },
211 { "NSMSG_MUST_TIME_OUT", "You must wait for cookies of that type to time out." },
212 { "NSMSG_ATE_COOKIE", "I ate the cookie for your account. You may now have another." },
213 { "NSMSG_ATE_FOREIGN_COOKIE", "I ate the cookie for account $b%s$b. It may now have another." },
214 { "NSMSG_USE_RENAME", "You are already authenticated to account $b%s$b -- contact the support staff to rename your account." },
215 { "NSMSG_ALREADY_REGISTERING", "You have already used $bREGISTER$b once this session; you may not use it again." },
216 { "NSMSG_REGISTER_BAD_NICKMASK", "You must provide a hostmask, or online nick to generate one automatically. (or set a default hostmask in the config such as *@*)." },
217 { "NSMSG_NICK_NOT_REGISTERED", "Nick $b%s$b has not been registered to any account." },
218 { "NSMSG_HANDLE_NOT_FOUND", "Could not find your account -- did you register yet?" },
219 { "NSMSG_ALREADY_AUTHED", "You are already authed to account $b%s$b; you must reconnect to auth to a different account." },
220 { "NSMSG_USE_AUTHCOOKIE", "Your hostmask is not valid for account $b%1$s$b. Please use the $bauthcookie$b command to grant yourself access. (/msg $S authcookie %1$s)" },
221 { "NSMSG_HOSTMASK_INVALID", "Your hostmask is not valid for account $b%s$b." },
222 { "NSMSG_USER_IS_SERVICE", "$b%s$b is a network service; you can only use that command on real users." },
223 { "NSMSG_USER_PREV_AUTH", "$b%s$b is already authenticated." },
224 { "NSMSG_USER_PREV_STAMP", "$b%s$b has authenticated to an account once and cannot authenticate again." },
225 { "NSMSG_BAD_MAX_LOGINS", "MaxLogins must be at most %d." },
226 { "NSMSG_BAD_ADVANCED", "Advanced must be either 1 to enable it or 0 to disable it." },
227 { "NSMSG_LANGUAGE_NOT_FOUND", "Language $b%s$b is not supported; $b%s$b was the closest available match." },
228 { "NSMSG_MAX_LOGINS", "Your account already has its limit of %d user(s) logged in." },
229 { "NSMSG_STAMPED_REGISTER", "You have already authenticated to an account once this session; you may not register a new account." },
230 { "NSMSG_STAMPED_AUTH", "You have already authenticated to an account once this session; you may not authenticate to another." },
231 { "NSMSG_STAMPED_RESETPASS", "You have already authenticated to an account once this session; you may not reset your password to authenticate again." },
232 { "NSMSG_STAMPED_AUTHCOOKIE", "You have already authenticated to an account once this session; you may not use a cookie to authenticate to another account." },
233 { "NSMSG_TITLE_INVALID", "Titles may contain only a-z, A-Z, 0-9, and '-'. Please choose another." },
234 { "NSMSG_TITLE_TRUNCATED", "That title combined with the user's account name would result in a truncated host; please choose a shorter title." },
235 { "NSMSG_FAKEHOST_INVALID", "Fake hosts must be shorter than %d characters and cannot start with a dot." },
236 { "NSMSG_HANDLEINFO_ON", "$bAccount Information for %s$b" },
237 { "NSMSG_HANDLEINFO_END", "----------End of Account Info-----------" },
238 { "NSMSG_HANDLEINFO_ID", "Account ID: %lu" },
239 { "NSMSG_HANDLEINFO_REGGED", "Registered on: %s" },
240 { "NSMSG_HANDLEINFO_LASTSEEN", "Last seen: %s" },
241 { "NSMSG_HANDLEINFO_LASTSEEN_NOW", "Last seen: Right now!" },
242 { "NSMSG_HANDLEINFO_KARMA", "Karma: %d" },
243 { "NSMSG_HANDLEINFO_VACATION", "On vacation." },
244 { "NSMSG_HANDLEINFO_EMAIL_ADDR", "Email address: %s" },
245 { "NSMSG_HANDLEINFO_COOKIE_ACTIVATION", "Cookie: There is currently an activation cookie issued for this account" },
246 { "NSMSG_HANDLEINFO_COOKIE_PASSWORD", "Cookie: There is currently a password change cookie issued for this account" },
247 { "NSMSG_HANDLEINFO_COOKIE_EMAIL", "Cookie: There is currently an email change cookie issued for this account" },
248 { "NSMSG_HANDLEINFO_COOKIE_ALLOWAUTH", "Cookie: There is currently an allowauth cookie issued for this account" },
249 { "NSMSG_HANDLEINFO_COOKIE_UNKNOWN", "Cookie: There is currently an unknown cookie issued for this account" },
250 { "NSMSG_HANDLEINFO_INFOLINE", "Infoline: %s" },
251 { "NSMSG_HANDLEINFO_FLAGS", "Flags: %s" },
252 { "NSMSG_HANDLEINFO_EPITHET", "Epithet: %s" },
253 { "NSMSG_HANDLEINFO_NOTE", "Note (by %s on %s): %s " },
254 { "NSMSG_HANDLEINFO_FAKEHOST", "Fake host: %s" },
255 { "NSMSG_INVALID_KARMA", "$b%s$b is not a valid karma modifier." },
256 { "NSMSG_SET_KARMA", "$bKARMA: $b%d$b" },
257 { "NSMSG_HANDLEINFO_LAST_HOST", "Last quit hostmask: %s" },
258 { "NSMSG_HANDLEINFO_LAST_HOST_UNKNOWN", "Last quit hostmask: Unknown" },
259 { "NSMSG_HANDLEINFO_NICKS", "Nickname(s): %s" },
260 { "NSMSG_HANDLEINFO_MASKS", "Hostmask(s): %s" },
261 { "NSMSG_HANDLEINFO_SSLFPS", "SSL Fingerprints(s): %s" },
262 { "NSMSG_HANDLEINFO_IGNORES", "Ignore(s): %s" },
263 { "NSMSG_HANDLEINFO_CHANNELS", "Channel(s): %s" },
264 { "NSMSG_HANDLEINFO_CURRENT", "Current nickname(s): %s" },
265 { "NSMSG_HANDLEINFO_DNR", "Do-not-register (by %s): %s" },
266 { "NSMSG_USERINFO_AUTHED_AS", "$b%s$b is authenticated to account $b%s$b." },
267 { "NSMSG_USERINFO_NOT_AUTHED", "$b%s$b is not authenticated to any account." },
268 { "NSMSG_NICKINFO_OWNER", "Nick $b%s$b is owned by account $b%s$b." },
269 { "NSMSG_PASSWORD_INVALID", "Incorrect password; please try again." },
270 { "NSMSG_PLEASE_SET_EMAIL", "We now require email addresses for users. Please use the $bset email$b command to set your email address!" },
271 { "NSMSG_WEAK_PASSWORD", "WARNING: You are using a password that is considered weak (easy to guess). It is STRONGLY recommended you change it (now, if not sooner) by typing \"/msg $S@$s PASS oldpass newpass\" (with your current password and a new password)." },
272 { "NSMSG_HANDLE_SUSPENDED", "Your $b$N$b account has been suspended; you may not use it." },
273 { "NSMSG_AUTH_SUCCESS", "I recognize you." },
274 { "NSMSG_ALLOWAUTH_STAFF", "$b%s$b is a helper or oper; please use $bstaff$b after the account name to allowauth." },
275 { "NSMSG_AUTH_ALLOWED", "User $b%s$b may now authenticate to account $b%s$b." },
276 { "NSMSG_AUTH_ALLOWED_MSG", "You may now authenticate to account $b%s$b by typing $b/msg $N@$s auth %s password$b (using your password). If you will be using this computer regularly, please type $b/msg $N addmask$b (AFTER you auth) to permanently add your hostmask." },
277 { "NSMSG_AUTH_ALLOWED_EMAIL", "You may also (after you auth) type $b/msg $N set email user@your.isp$b to set an email address. This will let you use the $bauthcookie$b command to be authenticated in the future." },
278 { "NSMSG_AUTH_NORMAL_ONLY", "User $b%s$b may now only authenticate to accounts with matching hostmasks." },
279 { "NSMSG_AUTH_UNSPECIAL", "User $b%s$b did not have any special auth allowance." },
280 { "NSMSG_MUST_AUTH", "You must be authenticated first." },
281 { "NSMSG_TOO_MANY_NICKS", "You have already registered the maximum permitted number of nicks." },
282 { "NSMSG_NICK_EXISTS", "Nick $b%s$b already registered." },
283 { "NSMSG_REGNICK_SUCCESS", "Nick $b%s$b has been registered to you." },
284 { "NSMSG_OREGNICK_SUCCESS", "Nick $b%s$b has been registered to account $b%s$b." },
285 { "NSMSG_PASS_SUCCESS", "Password changed." },
286 { "NSMSG_MASK_INVALID", "$b%s$b is an invalid hostmask." },
287 { "NSMSG_ADDMASK_ALREADY", "$b%s$b is already a hostmask in your account." },
288 { "NSMSG_ADDMASK_SUCCESS", "Hostmask %s added." },
289 { "NSMSG_ADDIGNORE_ALREADY", "$b%s$b is already an ignored hostmask in your account." },
290 { "NSMSG_ADDIGNORE_SUCCESS", "Hostmask %s added." },
291 { "NSMSG_ADDSSLFP_ALREADY", "$b%s$b is already an SSL fingerprint in your account." },
292 { "NSMSG_ADDSSLFP_SUCCESS", "SSL fingerprint %s added." },
293 { "NSMSG_DELMASK_NOTLAST", "You may not delete your last hostmask." },
294 { "NSMSG_DELMASK_SUCCESS", "Hostmask %s deleted." },
295 { "NSMSG_DELMASK_NOT_FOUND", "Unable to find mask to be deleted." },
296 { "NSMSG_DELSSLFP_SUCCESS", "SSL fingerprint %s deleted." },
297 { "NSMSG_DELSSLFP_NOT_FOUND", "Unable to find SSL fingerprint to be deleted." },
298 { "NSMSG_OPSERV_LEVEL_BAD", "You may not promote another oper above your level." },
299 { "NSMSG_USE_CMD_PASS", "Please use the PASS command to change your password." },
300 { "NSMSG_UNKNOWN_NICK", "I know nothing about nick $b%s$b." },
301 { "NSMSG_NOT_YOUR_NICK", "The nick $b%s$b is not registered to you." },
302 { "NSMSG_NICK_USER_YOU", "I will not let you kill yourself." },
303 { "NSMSG_UNREGNICK_SUCCESS", "Nick $b%s$b has been unregistered." },
304 { "NSMSG_UNREGISTER_SUCCESS", "Account $b%s$b has been unregistered." },
305 { "NSMSG_UNREGISTER_NICKS_SUCCESS", "Account $b%s$b and all its nicks have been unregistered." },
306 { "NSMSG_UNREGISTER_MUST_FORCE", "Account $b%s$b is not inactive or has special flags set; use FORCE to unregister it." },
307 { "NSMSG_UNREGISTER_CANNOT_FORCE", "Account $b%s$b is not inactive or has special flags set; have an IRCOp use FORCE to unregister it." },
308 { "NSMSG_UNREGISTER_NODELETE", "Account $b%s$b is protected from unregistration." },
309 { "NSMSG_HANDLE_STATS", "There are %d nicks registered to your account." },
310 { "NSMSG_HANDLE_NONE", "You are not authenticated against any account." },
311 { "NSMSG_GLOBAL_STATS", "There are %d accounts and %d nicks registered globally." },
312 { "NSMSG_GLOBAL_STATS_NONICK", "There are %d accounts registered." },
313 { "NSMSG_CANNOT_GHOST_SELF", "You may not ghost-kill yourself." },
314 { "NSMSG_CANNOT_GHOST_USER", "$b%s$b is not authed to your account; you may not ghost-kill them." },
315 { "NSMSG_GHOST_KILLED", "$b%s$b has been killed as a ghost." },
316 { "NSMSG_ON_VACATION", "You are now on vacation. Your account will be preserved until you authenticate again." },
317 { "NSMSG_NO_ACCESS", "Access denied." },
318 { "NSMSG_INVALID_FLAG", "$b%c$b is not a valid $N account flag." },
319 { "NSMSG_SET_FLAG", "Applied flags $b%s$b to %s's $N account." },
320 { "NSMSG_FLAG_PRIVILEGED", "You have insufficient access to set flag %c." },
321 { "NSMSG_DB_UNREADABLE", "Unable to read database file %s; check the log for more information." },
322 { "NSMSG_DB_MERGED", "$N merged DB from %s (in "FMT_TIME_T
".%03lu seconds)." },
323 { "NSMSG_HANDLE_CHANGED", "$b%s$b's account name has been changed to $b%s$b." },
324 { "NSMSG_BAD_HANDLE", "Account $b%s$b is not allowed because it is reserved, is too long, or contains invalid characters." },
325 { "NSMSG_BAD_NICK", "Nickname $b%s$b not registered because it is in use by a network service, is too long, or contains invalid characters." },
326 { "NSMSG_BAD_EMAIL_ADDR", "Please use a well-formed email address." },
327 { "NSMSG_FAIL_RENAME", "Account $b%s$b not renamed to $b%s$b because it is in use by a network services, or contains invalid characters." },
328 { "NSMSG_ACCOUNT_SEARCH_RESULTS", "The following accounts were found:" },
329 { "NSMSG_SEARCH_MATCH", "Match: %s" },
330 { "NSMSG_INVALID_ACTION", "%s is an invalid search action." },
331 { "NSMSG_CANNOT_MERGE_SELF", "You cannot merge account $b%s$b with itself." },
332 { "NSMSG_HANDLES_MERGED", "Merged account $b%s$b into $b%s$b." },
333 { "NSMSG_RECLAIM_WARN", "%s is a registered nick - you must auth to account %s or change your nick." },
334 { "NSMSG_RECLAIM_HOWTO", "To auth to account %s you must use /msg %s@%s AUTH %s <password>" },
335 { "NSMSG_RECLAIM_KILL", "Unauthenticated user of nick." },
336 { "NSMSG_RECLAIMED_NONE", "You cannot manually reclaim a nick." },
337 { "NSMSG_RECLAIMED_WARN", "Sent a request for %s to change their nick." },
338 { "NSMSG_RECLAIMED_SVSNICK", "Forcibly changed %s's nick." },
339 { "NSMSG_RECLAIMED_KILL", "Disconnected %s from the network." },
340 { "NSMSG_CLONE_AUTH", "Warning: %s (%s@%s) authed to your account." },
341 { "NSMSG_SETTING_LIST", "$b$N account settings$b" },
342 { "NSMSG_SETTING_LIST_HEADER", "----------------------------------------" },
343 { "NSMSG_SETTING_LIST_END", "-------------End Of Settings------------" },
344 { "NSMSG_INVALID_OPTION", "$b%s$b is an invalid account setting." },
345 { "NSMSG_INVALID_ANNOUNCE", "$b%s$b is an invalid announcements value." },
346 { "NSMSG_SET_INFO", "$bINFO: $b%s" },
347 { "NSMSG_SET_WIDTH", "$bWIDTH: $b%d" },
348 { "NSMSG_SET_TABLEWIDTH", "$bTABLEWIDTH: $b%d" },
349 { "NSMSG_SET_COLOR", "$bCOLOR: $b%s" },
350 { "NSMSG_SET_PRIVMSG", "$bPRIVMSG: $b%s" },
351 { "NSMSG_SET_STYLE", "$bSTYLE: $b%s" },
352 { "NSMSG_SET_ANNOUNCEMENTS", "$bANNOUNCEMENTS: $b%s" },
353 { "NSMSG_SET_AUTOHIDE", "$bAUTOHIDE: $b%s" },
354 { "NSMSG_SET_PASSWORD", "$bPASSWORD: $b%s" },
355 { "NSMSG_SET_FLAGS", "$bFLAGS: $b%s" },
356 { "NSMSG_SET_EMAIL", "$bEMAIL: $b%s" },
357 { "NSMSG_SET_MAXLOGINS", "$bMAXLOGINS: $b%d" },
358 { "NSMSG_SET_ADVANCED", "$bADVANCED: $b%s" },
359 { "NSMSG_SET_LANGUAGE", "$bLANGUAGE: $b%s" },
360 { "NSMSG_SET_LEVEL", "$bLEVEL: $b%d" },
361 { "NSMSG_SET_EPITHET", "$bEPITHET: $b%s" },
362 { "NSMSG_SET_NOTE", "$bNOTE: $b%s"},
363 { "NSMSG_SET_TITLE", "$bTITLE: $b%s" },
364 { "NSMSG_SET_FAKEHOST", "$bFAKEHOST: $b%s" },
366 { "NSMSG_AUTO_OPER", "You have been auto-opered" },
367 { "NSMSG_AUTO_OPER_ADMIN", "You have been auto-admined" },
369 { "NSEMAIL_ACTIVATION_SUBJECT", "Account verification for %s" },
370 { "NSEMAIL_ACTIVATION_BODY",
371 "This email has been sent to verify that this email address belongs to the person who tried to register an account on %1$s. Your cookie is:\n"
373 "To verify your email address and complete the account registration, log on to %1$s and type the following command:\n"
374 "/msg %3$s@%4$s COOKIE %5$s %2$s\n"
375 "This command is only used once to complete your account registration, and never again. Once you have run this command, you will need to authenticate everytime you reconnect to the network. To do this, you will have to type this command every time you reconnect:\n"
376 "/msg %3$s@%4$s AUTH %5$s your-password\n"
377 "(Please remember to fill in 'your-password' with the actual password you gave to us when you registered.)\n"
378 "OR configure Login-On-Connect (see http://www.afternet.org/login-on-connect for instructions) to connect pre-logged in every time.\n"
380 "If you did NOT request this account, you do not need to do anything.\n"
381 "Please contact the %1$s staff if you have questions, and be sure to check our website." },
382 { "NSEMAIL_ACTIVATION_BODY_WEB",
383 "This email has been sent to verify that this email address belongs to the person who tried to register an account on %1$s. Your cookie is:\n"
385 "To verify your email address and complete the account registration, visit the following URL:\n"
386 "http://www.afternet.org/index.php?option=com_registration&task=activate&username=%5$s&cookie=%2$s\n"
388 "If you did NOT request this account, you do not need to do anything.\n"
389 "Please contact the %1$s staff if you have questions, and be sure to check our website." },
390 { "NSEMAIL_PASSWORD_CHANGE_SUBJECT", "Password change verification on %s" },
391 { "NSEMAIL_PASSWORD_CHANGE_BODY",
392 "This email has been sent to verify that you wish to change the password on your account %5$s. Your cookie is %2$s.\n"
393 "To complete the password change, log on to %1$s and type the following command:\n"
394 "/msg %3$s@%4$s COOKIE %5$s %2$s\n"
395 "If you did NOT request your password to be changed, you do not need to do anything.\n"
396 "Please contact the %1$s staff if you have questions." },
397 { "NSEMAIL_PASSWORD_CHANGE_BODY_WEB",
398 "This email has been sent to verify that you wish to change the password on your account %5$s. Your cookie is %2$s.\n"
399 "To complete the password change, click the following URL:\n"
400 "http://www.afternet.org/index.php?option=com_registration&task=passcookie&username=%5$s&cookie=%2$s\n"
401 "If you did NOT request your password to be changed, you do not need to do anything.\n"
402 "Please contact the %1$s staff if you have questions." },
403 { "NSEMAIL_EMAIL_CHANGE_SUBJECT", "Email address change verification for %s" },
404 #ifdef stupid_verify_old_email
405 { "NSEMAIL_EMAIL_CHANGE_BODY_NEW", "This email has been sent to verify that your email address belongs to the same person as account %5$s on %1$s. The SECOND HALF of your cookie is %2$.*6$s.\nTo verify your address as associated with this account, log on to %1$s and type the following command:\n /msg %3$s@%4$s COOKIE %5$s ?????%2$.*6$s\n(Replace the ????? with the FIRST HALF of the cookie, as sent to your OLD email address.)\nIf you did NOT request this email address to be associated with this account, you do not need to do anything. Please contact the %1$s staff if you have questions." },
406 { "NSEMAIL_EMAIL_CHANGE_BODY_OLD", "This email has been sent to verify that you want to change your email for account %5$s on %1$s from this address to %7$s. The FIRST HALF of your cookie is %2$.*6$s\nTo verify your new address as associated with this account, log on to %1$s and type the following command:\n /msg %3$s@%4$s COOKIE %5$s %2$.*6$s?????\n(Replace the ????? with the SECOND HALF of the cookie, as sent to your NEW email address.)\nIf you did NOT request this change of email address, you do not need to do anything. Please contact the %1$s staff if you have questions." },
408 { "NSEMAIL_EMAIL_VERIFY_SUBJECT", "Email address verification for %s" },
409 { "NSEMAIL_EMAIL_VERIFY_BODY", "This email has been sent to verify that this address belongs to the same person as %5$s on %1$s. Your cookie is %2$s.\nTo verify your address as associated with this account, log on to %1$s and type the following command:\n /msg %3$s@%4$s COOKIE %5$s %2$s\nIf you did NOT request this email address to be associated with this account, you do not need to do anything. Please contact the %1$s staff if you have questions." },
410 { "NSEMAIL_ALLOWAUTH_SUBJECT", "Authentication allowed for %s" },
411 { "NSEMAIL_ALLOWAUTH_BODY", "This email has been sent to let you authenticate (auth) to account %5$s on %1$s. Your cookie is %2$s.\nTo auth to that account, log on to %1$s and type the following command:\n /msg %3$s@%4$s COOKIE %5$s %2$s\nIf you did NOT request this authorization, you do not need to do anything. Please contact the %1$s staff if you have questions." },
412 { "NSMSG_NOT_VALID_FAKEHOST_DOT", "$b%s$b is not a valid vhost. (needs at least one dot)" },
413 { "NSMSG_NOT_VALID_FAKEHOST_AT", "$b%s$b is not a valid vhost. (it can not have a '@')" },
414 { "NSMSG_DENIED_FAKEHOST_WORD", "Access denied because there's a prohibited word in $b%s$b (%s)." },
415 { "NSMSG_NOT_VALID_FAKEHOST_LEN", "$b%s$b is not a valid vhost. (can only be 63 characters)" },
416 { "NSMSG_NOT_VALID_FAKEHOST_TLD_LEN", "$b%s$b is not a valid vhost. (TLD can only be 4 characters and less)" },
417 { "NSMSG_NOT_VALID_FAKEHOST_REGEX", "$b%s$b is not allowed by the admin, consult the valid vhost regex pattern in the config file under nickserv/valid_fakehost_regex." },
418 { "CHECKPASS_YES", "Yes." },
419 { "CHECKPASS_NO", "No." },
420 { "CHECKEMAIL_NOT_SET", "No email set." },
421 { "CHECKEMAIL_YES", "Yes." },
422 { "CHECKEMAIL_NO", "No." },
423 { "NSMSG_DEFCON_NO_NEW_NICKS", "You cannot register new %s at this time, please try again soon" },
427 static void nickserv_reclaim(struct userNode
*user
, struct nick_info
*ni
, enum reclaim_action action
);
428 static void nickserv_reclaim_p(void *data
);
429 static int nickserv_addmask(struct userNode
*user
, struct handle_info
*hi
, const char *mask
);
431 struct nickserv_config nickserv_conf
;
433 /* We have 2^32 unique account IDs to use. */
434 unsigned long int highest_id
= 0;
437 canonicalize_hostmask(char *mask
)
439 char *out
= mask
, *temp
;
440 if ((temp
= strchr(mask
, '!'))) {
442 while (*temp
) *out
++ = *temp
++;
448 static struct handle_note
*
449 nickserv_add_note(const char *setter
, time_t date
, const char *text
)
451 struct handle_note
*note
= calloc(1, sizeof(*note
) + strlen(text
));
453 strncpy(note
->setter
, setter
, sizeof(note
->setter
)-1);
455 memcpy(note
->note
, text
, strlen(text
));
459 static struct handle_info
*
460 register_handle(const char *handle
, const char *passwd
, UNUSED_ARG(unsigned long id
))
462 struct handle_info
*hi
;
464 hi
= calloc(1, sizeof(*hi
));
465 hi
->userlist_style
= nickserv_conf
.default_style
? nickserv_conf
.default_style
: HI_DEFAULT_STYLE
;
466 hi
->announcements
= '?';
467 hi
->handle
= strdup(handle
);
468 safestrncpy(hi
->passwd
, passwd
, sizeof(hi
->passwd
));
470 dict_insert(nickserv_handle_dict
, hi
->handle
, hi
);
476 register_nick(const char *nick
, struct handle_info
*owner
)
478 struct nick_info
*ni
;
479 ni
= malloc(sizeof(struct nick_info
));
480 safestrncpy(ni
->nick
, nick
, sizeof(ni
->nick
));
482 ni
->next
= owner
->nicks
;
484 dict_insert(nickserv_nick_dict
, ni
->nick
, ni
);
488 delete_nick(struct nick_info
*ni
)
490 struct nick_info
*last
, *next
;
491 struct userNode
*user
;
492 /* Check to see if we should mark a user as unregistered. */
493 if ((user
= GetUserH(ni
->nick
)) && IsReggedNick(user
)) {
494 user
->modes
&= ~FLAGS_REGNICK
;
497 /* Remove ni from the nick_info linked list. */
498 if (ni
== ni
->owner
->nicks
) {
499 ni
->owner
->nicks
= ni
->next
;
501 last
= ni
->owner
->nicks
;
507 last
->next
= next
->next
;
509 dict_remove(nickserv_nick_dict
, ni
->nick
);
512 static unreg_func_t
*unreg_func_list
;
513 static void **unreg_func_list_extra
;
514 static unsigned int unreg_func_size
= 0, unreg_func_used
= 0;
517 reg_unreg_func(unreg_func_t func
, void *extra
)
519 if (unreg_func_used
== unreg_func_size
) {
520 if (unreg_func_size
) {
521 unreg_func_size
<<= 1;
522 unreg_func_list
= realloc(unreg_func_list
, unreg_func_size
*sizeof(unreg_func_t
));
523 unreg_func_list_extra
= realloc(unreg_func_list_extra
, unreg_func_size
*sizeof(void*));
526 unreg_func_list
= malloc(unreg_func_size
*sizeof(unreg_func_t
));
527 unreg_func_list_extra
= malloc(unreg_func_size
*sizeof(void*));
530 unreg_func_list
[unreg_func_used
] = func
;
531 unreg_func_list_extra
[unreg_func_used
++] = extra
;
535 nickserv_free_cookie(void *data
)
537 struct handle_cookie
*cookie
= data
;
538 if (cookie
->hi
) cookie
->hi
->cookie
= NULL
;
539 if (cookie
->data
) free(cookie
->data
);
544 free_handle_info(void *vhi
)
546 struct handle_info
*hi
= vhi
;
548 free_string_list(hi
->masks
);
549 free_string_list(hi
->sslfps
);
550 free_string_list(hi
->ignores
);
554 delete_nick(hi
->nicks
);
560 timeq_del(hi
->cookie
->expires
, nickserv_free_cookie
, hi
->cookie
, 0);
561 nickserv_free_cookie(hi
->cookie
);
563 if (hi
->email_addr
) {
564 struct handle_info_list
*hil
= dict_find(nickserv_email_dict
, hi
->email_addr
, NULL
);
565 handle_info_list_remove(hil
, hi
);
567 dict_remove(nickserv_email_dict
, hi
->email_addr
);
572 static void set_user_handle_info(struct userNode
*user
, struct handle_info
*hi
, int stamp
);
575 nickserv_unregister_handle(struct handle_info
*hi
, struct userNode
*notify
, struct userNode
*bot
)
578 struct userNode
*uNode
;
581 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
583 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
584 if( (rc
= ldap_delete_account(hi
->handle
)) != LDAP_SUCCESS
) {
586 send_message(notify
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
588 if(rc
!= LDAP_NO_SUCH_OBJECT
)
589 return false; /* if theres noone there to delete, its kinda ok, right ?:) */
594 for (n
=0; n
<unreg_func_used
; n
++)
595 unreg_func_list
[n
](notify
, hi
, unreg_func_list_extra
[n
]);
597 if (nickserv_conf
.sync_log
) {
598 uNode
= GetUserH(hi
->users
->nick
);
602 set_user_handle_info(hi
->users
, NULL
, 0);
605 if (nickserv_conf
.disable_nicks
)
606 send_message(notify
, bot
, "NSMSG_UNREGISTER_SUCCESS", hi
->handle
);
608 send_message(notify
, bot
, "NSMSG_UNREGISTER_NICKS_SUCCESS", hi
->handle
);
611 if (nickserv_conf
.sync_log
)
612 SyncLog("UNREGISTER %s", hi
->handle
);
614 dict_remove(nickserv_handle_dict
, hi
->handle
);
619 get_handle_info(const char *handle
)
621 return dict_find(nickserv_handle_dict
, handle
, 0);
625 get_nick_info(const char *nick
)
627 return nickserv_conf
.disable_nicks
? 0 : dict_find(nickserv_nick_dict
, nick
, 0);
631 find_handle_in_channel(struct chanNode
*channel
, struct handle_info
*handle
, struct userNode
*except
)
636 for (nn
=0; nn
<channel
->members
.used
; ++nn
) {
637 mn
= channel
->members
.list
[nn
];
638 if ((mn
->user
!= except
) && (mn
->user
->handle_info
== handle
))
645 oper_has_access(struct userNode
*user
, struct userNode
*bot
, unsigned int min_level
, unsigned int quiet
) {
646 if (!user
->handle_info
) {
648 send_message(user
, bot
, "MSG_AUTHENTICATE");
652 if (!IsOper(user
) && (!IsHelping(user
) || min_level
)) {
654 send_message(user
, bot
, "NSMSG_NO_ACCESS");
658 if (HANDLE_FLAGGED(user
->handle_info
, OPER_SUSPENDED
)) {
660 send_message(user
, bot
, "MSG_OPER_SUSPENDED");
664 if (user
->handle_info
->opserv_level
< min_level
) {
666 send_message(user
, bot
, "NSMSG_NO_ACCESS");
674 is_valid_handle(const char *handle
)
676 struct userNode
*user
;
677 /* cant register a juped nick/service nick as handle, to prevent confusion */
678 user
= GetUserH(handle
);
679 if (user
&& IsLocal(user
))
681 /* check against maximum length */
682 if (strlen(handle
) > NICKSERV_HANDLE_LEN
)
684 /* for consistency, only allow account names that could be nicks */
685 if (!is_valid_nick(handle
))
687 /* disallow account names that look like bad words */
688 if (opserv_bad_channel(handle
))
690 /* test either regex or containing all valid chars */
691 if (nickserv_conf
.valid_handle_regex_set
) {
692 int err
= regexec(&nickserv_conf
.valid_handle_regex
, handle
, 0, 0, 0);
695 buff
[regerror(err
, &nickserv_conf
.valid_handle_regex
, buff
, sizeof(buff
))] = 0;
696 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
700 return !handle
[strspn(handle
, NICKSERV_VALID_CHARS
)];
705 is_registerable_nick(const char *nick
)
707 struct userNode
*user
;
708 /* cant register a juped nick/service nick as nick, to prevent confusion */
709 user
= GetUserH(nick
);
710 if (user
&& IsLocal(user
))
712 /* for consistency, only allow nicks names that could be nicks */
713 if (!is_valid_nick(nick
))
715 /* disallow nicks that look like bad words */
716 if (opserv_bad_channel(nick
))
719 if (strlen(nick
) > NICKLEN
)
721 /* test either regex or as valid handle */
722 if (nickserv_conf
.valid_nick_regex_set
) {
723 int err
= regexec(&nickserv_conf
.valid_nick_regex
, nick
, 0, 0, 0);
726 buff
[regerror(err
, &nickserv_conf
.valid_nick_regex
, buff
, sizeof(buff
))] = 0;
727 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
733 /* this has been replaced with one in tools.c
736 is_valid_email_addr(const char *email)
738 return strchr(email, '@') != NULL;
744 visible_email_addr(struct userNode
*user
, struct handle_info
*hi
)
746 if (hi
->email_addr
) {
747 if (oper_has_access(user
, nickserv
, nickserv_conf
.email_visible_level
, 1)) {
748 return hi
->email_addr
;
758 smart_get_handle_info(struct userNode
*service
, struct userNode
*user
, const char *name
)
760 struct handle_info
*hi
;
761 struct userNode
*target
;
765 if (!(hi
= get_handle_info(++name
))) {
766 send_message(user
, service
, "MSG_HANDLE_UNKNOWN", name
);
771 if (!(target
= GetUserH(name
))) {
772 send_message(user
, service
, "MSG_NICK_UNKNOWN", name
);
775 if (IsLocal(target
)) {
776 if (IsService(target
))
777 send_message(user
, service
, "NSMSG_USER_IS_SERVICE", target
->nick
);
779 send_message(user
, service
, "MSG_USER_AUTHENTICATE", target
->nick
);
782 if (!(hi
= target
->handle_info
)) {
783 send_message(user
, service
, "MSG_USER_AUTHENTICATE", target
->nick
);
791 oper_outranks(struct userNode
*user
, struct handle_info
*hi
) {
792 if (user
->handle_info
->opserv_level
> hi
->opserv_level
)
794 if (user
->handle_info
->opserv_level
== hi
->opserv_level
) {
795 if ((user
->handle_info
->opserv_level
== 1000)
796 || (user
->handle_info
== hi
)
797 || ((user
->handle_info
->opserv_level
== 0)
798 && !(HANDLE_FLAGGED(hi
, SUPPORT_HELPER
) || HANDLE_FLAGGED(hi
, NETWORK_HELPER
))
799 && HANDLE_FLAGGED(user
->handle_info
, HELPING
))) {
803 send_message(user
, nickserv
, "MSG_USER_OUTRANKED", hi
->handle
);
808 get_victim_oper(struct userNode
*user
, const char *target
)
810 struct handle_info
*hi
;
811 if (!(hi
= smart_get_handle_info(nickserv
, user
, target
)))
813 if (HANDLE_FLAGGED(user
->handle_info
, OPER_SUSPENDED
)) {
814 send_message(user
, nickserv
, "MSG_OPER_SUSPENDED");
817 return oper_outranks(user
, hi
) ? hi
: NULL
;
821 valid_user_for(struct userNode
*user
, struct handle_info
*hi
)
825 /* If no hostmasks on the account, allow it. */
826 if (!hi
->masks
->used
)
828 /* If any hostmask matches, allow it. */
829 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
830 if (user_matches_glob(user
, hi
->masks
->list
[ii
], 0, 0))
832 /* If they are allowauthed to this account, allow it (removing the aa). */
833 if (dict_find(nickserv_allow_auth_dict
, user
->nick
, NULL
) == hi
) {
834 dict_remove(nickserv_allow_auth_dict
, user
->nick
);
837 /* The user is not allowed to use this account. */
842 valid_user_sslfp(struct userNode
*user
, struct handle_info
*hi
)
846 if (!hi
->sslfps
->used
)
851 /* If any SSL fingerprint matches, allow it. */
852 for (ii
=0; ii
<hi
->sslfps
->used
; ii
++)
853 if (!irccasecmp(user
->sslfp
, hi
->sslfps
->list
[ii
]))
856 /* No valid SSL fingerprint found. */
861 is_secure_password(const char *handle
, const char *pass
, struct userNode
*user
)
864 unsigned int cnt_digits
= 0, cnt_upper
= 0, cnt_lower
= 0;
868 if (len
< nickserv_conf
.password_min_length
) {
870 send_message(user
, nickserv
, "NSMSG_PASSWORD_SHORT", nickserv_conf
.password_min_length
);
873 if (!irccasecmp(pass
, handle
)) {
875 send_message(user
, nickserv
, "NSMSG_PASSWORD_ACCOUNT");
878 dict_find(nickserv_conf
.weak_password_dict
, pass
, &p
);
881 send_message(user
, nickserv
, "NSMSG_PASSWORD_DICTIONARY");
884 for (i
=0; i
<len
; i
++) {
885 if (isdigit(pass
[i
]))
887 if (isupper(pass
[i
]))
889 if (islower(pass
[i
]))
892 if ((cnt_lower
< nickserv_conf
.password_min_lower
)
893 || (cnt_upper
< nickserv_conf
.password_min_upper
)
894 || (cnt_digits
< nickserv_conf
.password_min_digits
)) {
896 send_message(user
, nickserv
, "NSMSG_PASSWORD_READABLE", nickserv_conf
.password_min_digits
, nickserv_conf
.password_min_upper
, nickserv_conf
.password_min_lower
);
902 static auth_func_t
*auth_func_list
;
903 static void **auth_func_list_extra
;
904 static unsigned int auth_func_size
= 0, auth_func_used
= 0;
907 reg_auth_func(auth_func_t func
, void *extra
)
909 if (auth_func_used
== auth_func_size
) {
910 if (auth_func_size
) {
911 auth_func_size
<<= 1;
912 auth_func_list
= realloc(auth_func_list
, auth_func_size
*sizeof(auth_func_t
));
913 auth_func_list_extra
= realloc(auth_func_list_extra
, auth_func_size
*sizeof(void*));
916 auth_func_list
= malloc(auth_func_size
*sizeof(auth_func_t
));
917 auth_func_list_extra
= malloc(auth_func_size
*sizeof(void*));
920 auth_func_list
[auth_func_used
] = func
;
921 auth_func_list_extra
[auth_func_used
++] = extra
;
924 static handle_rename_func_t
*rf_list
;
925 static void **rf_list_extra
;
926 static unsigned int rf_list_size
, rf_list_used
;
929 reg_handle_rename_func(handle_rename_func_t func
, void *extra
)
931 if (rf_list_used
== rf_list_size
) {
934 rf_list
= realloc(rf_list
, rf_list_size
*sizeof(rf_list
[0]));
935 rf_list_extra
= realloc(rf_list_extra
, rf_list_size
*sizeof(void*));
938 rf_list
= malloc(rf_list_size
*sizeof(rf_list
[0]));
939 rf_list_extra
= malloc(rf_list_size
*sizeof(void*));
942 rf_list
[rf_list_used
] = func
;
943 rf_list_extra
[rf_list_used
++] = extra
;
947 generate_fakehost(struct handle_info
*handle
)
949 struct userNode
*target
;
950 extern const char *hidden_host_suffix
;
951 static char buffer
[HOSTLEN
+1];
955 if (!handle
->fakehost
) {
956 data
= conf_get_data("server/hidden_host_type", RECDB_QSTRING
);
961 snprintf(buffer
, sizeof(buffer
), "%s.%s", handle
->handle
, hidden_host_suffix
);
962 else if (style
== 2) {
963 /* Due to the way fakehost is coded theres no way i can
964 get the exact user, so for now ill just take the first
966 for (target
= handle
->users
; target
; target
= target
->next_authed
)
969 snprintf(buffer
, sizeof(buffer
), "%s", target
->crypthost
);
972 } else if (handle
->fakehost
[0] == '.') {
973 /* A leading dot indicates the stored value is actually a title. */
974 snprintf(buffer
, sizeof(buffer
), "%s.%s.%s", handle
->handle
, handle
->fakehost
+1, nickserv_conf
.titlehost_suffix
);
977 return handle
->fakehost
;
981 apply_fakehost(struct handle_info
*handle
)
983 struct userNode
*target
;
988 fake
= generate_fakehost(handle
);
989 for (target
= handle
->users
; target
; target
= target
->next_authed
)
990 assign_fakehost(target
, fake
, 1);
993 void send_func_list(struct userNode
*user
)
996 struct handle_info
*old_info
;
998 old_info
= user
->handle_info
;
1000 for (n
=0; n
<auth_func_used
; n
++)
1001 auth_func_list
[n
](user
, old_info
, auth_func_list_extra
[n
]);
1005 set_user_handle_info(struct userNode
*user
, struct handle_info
*hi
, int stamp
)
1008 struct handle_info
*old_info
;
1010 /* This can happen if somebody uses COOKIE while authed, or if
1011 * they re-auth to their current handle (which is silly, but users
1012 * are like that). */
1013 if (user
->handle_info
== hi
)
1016 if (user
->handle_info
) {
1017 struct userNode
*other
;
1020 userList_remove(&curr_helpers
, user
);
1022 /* remove from next_authed linked list */
1023 if (user
->handle_info
->users
== user
) {
1024 user
->handle_info
->users
= user
->next_authed
;
1025 } else if (user
->handle_info
->users
!= NULL
) {
1026 for (other
= user
->handle_info
->users
;
1027 other
->next_authed
!= user
;
1028 other
= other
->next_authed
) ;
1029 other
->next_authed
= user
->next_authed
;
1031 /* No users authed to the account - can happen if they get
1032 * killed for authing. */
1034 /* if nobody left on old handle, and they're not an oper, remove !god */
1035 if (!user
->handle_info
->users
&& !user
->handle_info
->opserv_level
)
1036 HANDLE_CLEAR_FLAG(user
->handle_info
, HELPING
);
1037 /* record them as being last seen at this time */
1038 user
->handle_info
->lastseen
= now
;
1039 /* and record their hostmask */
1040 snprintf(user
->handle_info
->last_quit_host
, sizeof(user
->handle_info
->last_quit_host
), "%s@%s", user
->ident
, user
->hostname
);
1042 old_info
= user
->handle_info
;
1043 user
->handle_info
= hi
;
1044 if (hi
&& !hi
->users
&& !hi
->opserv_level
)
1045 HANDLE_CLEAR_FLAG(hi
, HELPING
);
1047 /* Call auth handlers */
1048 if (!GetUserH(user
->nick
))
1052 struct nick_info
*ni
;
1054 HANDLE_CLEAR_FLAG(hi
, FROZEN
);
1055 if (nickserv_conf
.warn_clone_auth
) {
1056 struct userNode
*other
;
1057 for (other
= hi
->users
; other
; other
= other
->next_authed
)
1058 send_message(other
, nickserv
, "NSMSG_CLONE_AUTH", user
->nick
, user
->ident
, user
->hostname
);
1061 /* Add this auth to users list of current auths */
1062 user
->next_authed
= hi
->users
;
1065 /* Add to helpers list */
1066 if (IsHelper(user
) && !userList_contains(&curr_helpers
, user
))
1067 userList_append(&curr_helpers
, user
);
1069 /* Set the fakehost */
1070 if (hi
->fakehost
|| old_info
)
1074 #ifdef WITH_PROTOCOL_P10
1075 /* Stamp users with their account name. */
1076 char *id
= hi
->handle
;
1078 const char *id
= "???";
1080 /* Mark all the nicks registered to this
1081 * account as registered nicks
1082 * - Why not just this one? -rubin */
1083 if (!nickserv_conf
.disable_nicks
) {
1084 struct nick_info
*ni2
;
1085 for (ni2
= hi
->nicks
; ni2
; ni2
= ni2
->next
) {
1086 if (!irccasecmp(user
->nick
, ni2
->nick
)) {
1087 user
->modes
|= FLAGS_REGNICK
;
1092 /* send the account to the ircd */
1093 StampUser(user
, id
, hi
->registered
);
1096 /* Stop trying to kick this user off their nick */
1097 if ((ni
= get_nick_info(user
->nick
)) && (ni
->owner
== hi
))
1098 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
1100 /* We cannot clear the user's account ID, unfortunately. */
1101 user
->next_authed
= NULL
;
1104 /* Call auth handlers */
1105 if (GetUserH(user
->nick
)) {
1106 for (n
=0; n
<auth_func_used
; n
++) {
1107 auth_func_list
[n
](user
, old_info
, auth_func_list_extra
[n
]);
1114 static struct handle_info
*
1115 nickserv_register(struct userNode
*user
, struct userNode
*settee
, const char *handle
, const char *passwd
, int no_auth
)
1117 struct handle_info
*hi
;
1118 struct nick_info
*ni
;
1119 char crypted
[MD5_CRYPT_LENGTH
];
1121 if ((hi
= dict_find(nickserv_handle_dict
, handle
, NULL
))) {
1123 send_message(user
, nickserv
, "NSMSG_HANDLE_EXISTS", handle
);
1127 if(strlen(handle
) > 30)
1130 send_message(user
, nickserv
, "NSMSG_HANDLE_TOLONG", handle
, 30);
1134 if (!is_secure_password(handle
, passwd
, user
))
1137 cryptpass(passwd
, crypted
);
1139 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1141 rc
= ldap_do_add(handle
, (no_auth
? NULL
: crypted
), NULL
);
1142 if(LDAP_SUCCESS
!= rc
&& LDAP_ALREADY_EXISTS
!= rc
) {
1144 send_message(user
, nickserv
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
1149 hi
= register_handle(handle
, crypted
, 0);
1150 hi
->masks
= alloc_string_list(1);
1151 hi
->sslfps
= alloc_string_list(1);
1152 hi
->ignores
= alloc_string_list(1);
1154 hi
->language
= lang_C
;
1155 hi
->registered
= now
;
1157 hi
->flags
= HI_DEFAULT_FLAGS
;
1158 if (settee
&& !no_auth
)
1159 set_user_handle_info(settee
, hi
, 1);
1161 if (user
!= settee
) {
1163 send_message(user
, nickserv
, "NSMSG_OREGISTER_H_SUCCESS");
1165 else if (nickserv_conf
.disable_nicks
) {
1167 send_message(user
, nickserv
, "NSMSG_REGISTER_H_SUCCESS");
1170 else if (user
&& (ni
= dict_find(nickserv_nick_dict
, user
->nick
, NULL
))) {
1172 send_message(user
, nickserv
, "NSMSG_PARTIAL_REGISTER");
1177 if (is_registerable_nick(user
->nick
)) {
1178 register_nick(user
->nick
, hi
);
1179 send_message(user
, nickserv
, "NSMSG_REGISTER_HN_SUCCESS");
1183 if (is_registerable_nick(handle
)) {
1184 register_nick(handle
, hi
);
1188 if (settee
&& (user
!= settee
)) {
1190 send_message(settee
, nickserv
, "NSMSG_OREGISTER_VICTIM", user
->nick
, hi
->handle
);
1197 nickserv_bake_cookie(struct handle_cookie
*cookie
)
1199 cookie
->hi
->cookie
= cookie
;
1200 timeq_add(cookie
->expires
, nickserv_free_cookie
, cookie
);
1203 /* Contributed by the great sneep of afternet ;) */
1204 /* Since this gets used in a URL, we want to avoid stuff that confuses
1205 * email clients such as ] and ?. a-z, 0-9 only.
1207 void genpass(char *str
, int len
)
1212 for(i
= 0; i
< len
; i
++)
1216 c
= (char)((float)rand() / (float)RAND_MAX
* (float)256);
1217 } while(!((c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z') || (c
>= '0' && c
<= '9')));
1225 nickserv_make_cookie(struct userNode
*user
, struct handle_info
*hi
, enum cookie_type type
, const char *cookie_data
, int weblink
)
1227 struct handle_cookie
*cookie
;
1228 char subject
[128], body
[4096], *misc
;
1229 const char *netname
, *fmt
;
1233 send_message(user
, nickserv
, "NSMSG_COOKIE_LIVE", hi
->handle
);
1237 cookie
= calloc(1, sizeof(*cookie
));
1239 cookie
->type
= type
;
1240 cookie
->data
= cookie_data
? strdup(cookie_data
) : NULL
;
1242 cookie
->expires
= now
+ nickserv_conf
.cookie_timeout
;
1243 /* Adding dedicated password gen function for more control -Rubin */
1244 genpass(cookie
->cookie
, 10);
1246 *inttobase64(cookie->cookie, rand(), 5);
1247 *inttobase64(cookie->cookie+5, rand(), 5);
1250 netname
= nickserv_conf
.network_name
;
1253 switch (cookie
->type
) {
1255 hi
->passwd
[0] = 0; /* invalidate password */
1256 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_REGISTER");
1257 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_SUBJECT");
1258 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1261 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_BODY_WEB");
1263 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_BODY");
1265 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1268 case PASSWORD_CHANGE
:
1269 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_RESETPASS");
1270 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_SUBJECT");
1271 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1273 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_BODY_WEB");
1275 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_BODY");
1276 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1280 misc
= hi
->email_addr
;
1281 hi
->email_addr
= cookie
->data
;
1282 #ifdef stupid_verify_old_email
1284 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_EMAIL_2");
1285 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_SUBJECT");
1286 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1287 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_BODY_NEW");
1288 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
+COOKIELEN
/2, nickserv
->nick
, self
->name
, hi
->handle
, COOKIELEN
/2);
1289 mail_send(nickserv
, hi
, subject
, body
, 1);
1290 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_BODY_OLD");
1291 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
, COOKIELEN
/2, hi
->email_addr
);
1295 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_EMAIL_1");
1296 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_VERIFY_SUBJECT");
1297 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1298 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_VERIFY_BODY");
1299 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1300 mail_send(nickserv
, hi
, subject
, body
, 1);
1302 #ifdef stupid_verify_old_email
1305 hi
->email_addr
= misc
;
1308 fmt
= handle_find_message(hi
, "NSEMAIL_ALLOWAUTH_SUBJECT");
1309 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1310 fmt
= handle_find_message(hi
, "NSEMAIL_ALLOWAUTH_BODY");
1311 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1312 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_AUTH");
1315 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d in nickserv_make_cookie.", cookie
->type
);
1319 mail_send(nickserv
, hi
, subject
, body
, first_time
);
1320 nickserv_bake_cookie(cookie
);
1324 nickserv_eat_cookie(struct handle_cookie
*cookie
)
1326 cookie
->hi
->cookie
= NULL
;
1327 timeq_del(cookie
->expires
, nickserv_free_cookie
, cookie
, 0);
1328 nickserv_free_cookie(cookie
);
1332 nickserv_free_email_addr(void *data
)
1334 handle_info_list_clean(data
);
1339 nickserv_set_email_addr(struct handle_info
*hi
, const char *new_email_addr
)
1341 struct handle_info_list
*hil
;
1342 /* Remove from old handle_info_list ... */
1343 if (hi
->email_addr
&& (hil
= dict_find(nickserv_email_dict
, hi
->email_addr
, 0))) {
1344 handle_info_list_remove(hil
, hi
);
1345 if (!hil
->used
) dict_remove(nickserv_email_dict
, hil
->tag
);
1346 hi
->email_addr
= NULL
;
1348 /* Add to the new list.. */
1349 if (new_email_addr
) {
1350 if (!(hil
= dict_find(nickserv_email_dict
, new_email_addr
, 0))) {
1351 hil
= calloc(1, sizeof(*hil
));
1352 hil
->tag
= strdup(new_email_addr
);
1353 handle_info_list_init(hil
);
1354 dict_insert(nickserv_email_dict
, hil
->tag
, hil
);
1356 handle_info_list_append(hil
, hi
);
1357 hi
->email_addr
= hil
->tag
;
1361 static NICKSERV_FUNC(cmd_register
)
1364 struct handle_info
*hi
;
1365 const char *email_addr
, *password
;
1366 char syncpass
[MD5_CRYPT_LENGTH
];
1367 int no_auth
, weblink
;
1369 if (checkDefCon(DEFCON_NO_NEW_NICKS
) && !IsOper(user
)) {
1370 reply("NSMSG_DEFCON_NO_NEW_NICKS", nickserv_conf
.disable_nicks
? "accounts" : "nicknames");
1374 if (!IsOper(user
) && !dict_size(nickserv_handle_dict
)) {
1375 /* Require the first handle registered to belong to someone +o. */
1376 reply("NSMSG_REQUIRE_OPER");
1380 if (user
->handle_info
) {
1381 reply("NSMSG_USE_RENAME", user
->handle_info
->handle
);
1385 if (IsRegistering(user
)) {
1386 reply("NSMSG_ALREADY_REGISTERING");
1390 if (IsStamped(user
)) {
1391 /* Unauthenticated users might still have been stamped
1392 previously and could therefore have a hidden host;
1393 do not allow them to register a new account. */
1394 reply("NSMSG_STAMPED_REGISTER");
1398 NICKSERV_MIN_PARMS((unsigned)3 + nickserv_conf
.email_required
);
1400 if(nickserv_conf
.force_handles_lowercase
)
1401 irc_strtolower(argv
[1]);
1402 if (!is_valid_handle(argv
[1])) {
1403 reply("NSMSG_BAD_HANDLE", argv
[1]);
1408 if ((argc
>= 4) && nickserv_conf
.email_enabled
) {
1409 struct handle_info_list
*hil
;
1412 /* Remember email address. */
1413 email_addr
= argv
[3];
1415 /* Check that the email address looks valid.. */
1416 if (!valid_email(email_addr
)) {
1417 reply("NSMSG_BAD_EMAIL_ADDR");
1421 /* .. and that we are allowed to send to it. */
1422 if ((str
= mail_prohibited_address(email_addr
))) {
1423 reply("NSMSG_EMAIL_PROHIBITED", email_addr
, str
);
1427 /* If we do email verify, make sure we don't spam the address. */
1428 if ((hil
= dict_find(nickserv_email_dict
, email_addr
, NULL
))) {
1430 for (nn
=0; nn
<hil
->used
; nn
++) {
1431 if (hil
->list
[nn
]->cookie
) {
1432 reply("NSMSG_EMAIL_UNACTIVATED");
1436 if (hil
->used
>= nickserv_conf
.handles_per_email
) {
1437 reply("NSMSG_EMAIL_OVERUSED");
1450 /* Webregister hack - send URL instead of IRC cookie
1453 if((argc
>= 5) && !strcmp(argv
[4],"WEBLINK"))
1457 if (!(hi
= nickserv_register(user
, user
, argv
[1], password
, no_auth
)))
1459 /* Add any masks they should get. */
1460 if (nickserv_conf
.default_hostmask
) {
1461 string_list_append(hi
->masks
, strdup("*@*"));
1463 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
1464 if (irc_in_addr_is_valid(user
->ip
) && !irc_pton(&ip
, NULL
, user
->hostname
))
1465 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_BYIP
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
1468 /* If they're the first to register, give them level 1000. */
1469 if (dict_size(nickserv_handle_dict
) == 1) {
1470 hi
->opserv_level
= 1000;
1471 reply("NSMSG_ROOT_HANDLE", argv
[1]);
1474 /* Set their email address. */
1477 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1479 if((rc
= ldap_do_modify(hi
->handle
, NULL
, email_addr
)) != LDAP_SUCCESS
) {
1480 /* Falied to update email in ldap, but still
1481 * updated it here.. what should we do? */
1482 reply("NSMSG_LDAP_FAIL_EMAIL", ldap_err2string(rc
));
1484 nickserv_set_email_addr(hi
, email_addr
);
1488 nickserv_set_email_addr(hi
, email_addr
);
1491 nickserv_set_email_addr(hi
, email_addr
);
1495 /* If they need to do email verification, tell them. */
1497 nickserv_make_cookie(user
, hi
, ACTIVATION
, hi
->passwd
, weblink
);
1499 /* Set registering flag.. */
1500 user
->modes
|= FLAGS_REGISTERING
;
1502 if (nickserv_conf
.sync_log
) {
1503 cryptpass(password
, syncpass
);
1505 * An 0 is only sent if theres no email address. Thios should only happen if email functions are
1506 * disabled which they wont be for us. Email Required MUST be set on if you are using this.
1509 SyncLog("REGISTER %s %s %s %s", hi
->handle
, syncpass
, email_addr
? email_addr
: "0", user
->info
);
1512 /* this wont work if email is required .. */
1513 process_adduser_pending(user
);
1518 static NICKSERV_FUNC(cmd_oregister
)
1520 struct userNode
*settee
= NULL
;
1521 struct handle_info
*hi
;
1522 char* account
= NULL
;
1528 NICKSERV_MIN_PARMS(2);
1532 if(nickserv_conf
.force_handles_lowercase
)
1533 irc_strtolower(account
);
1534 if (!is_valid_handle(argv
[1])) {
1535 reply("NSMSG_BAD_HANDLE", argv
[1]);
1538 if (nickserv_conf
.email_required
) {
1539 NICKSERV_MIN_PARMS(3);
1541 if (argc
> 4) {/* take: "acct pass email mask nick" or "acct pass email mask" or "acct pass email nick" */
1542 if (strchr(argv
[4], '@'))
1552 if (argc
> 3) {/* take: "account pass mask nick" or "account pass mask" or "account pass nick" */
1553 if (strchr(argv
[3], '@'))
1562 /* If they passed a nick, look for that user.. */
1563 if (nick
&& !(settee
= GetUserH(nick
))) {
1564 reply("MSG_NICK_UNKNOWN", argv
[4]);
1567 /* If the setee is already authed, we cant add a 2nd account for them.. */
1568 if (settee
&& settee
->handle_info
) {
1569 reply("NSMSG_USER_PREV_AUTH", settee
->nick
);
1572 /* If there is no default mask in the conf, and they didn't pass a mask,
1573 * but we did find a user by nick, generate the mask */
1575 if (nickserv_conf
.default_hostmask
)
1578 mask
= generate_hostmask(settee
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
1580 reply("NSMSG_REGISTER_BAD_NICKMASK");
1585 if (!(hi
= nickserv_register(user
, settee
, account
, pass
, 0))) {
1586 return 0; /* error reply handled by above */
1590 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1592 if((rc
= ldap_do_modify(hi
->handle
, NULL
, email
)) != LDAP_SUCCESS
) {
1593 /* Falied to update email in ldap, but still
1594 * updated it here.. what should we do? */
1595 reply("NSMSG_LDAP_FAIL_EMAIL", ldap_err2string(rc
));
1597 nickserv_set_email_addr(hi
, email
);
1601 nickserv_set_email_addr(hi
, email
);
1604 nickserv_set_email_addr(hi
, email
);
1608 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
1609 if (mask_canonicalized
)
1610 string_list_append(hi
->masks
, mask_canonicalized
);
1613 if (nickserv_conf
.sync_log
)
1614 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, email
? email
: "@", user
->info
); /* Send just @ for email if none */
1619 nickserv_ignore(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, char *mask
)
1622 struct userNode
*target
;
1623 char *new_mask
= strdup(pretty_mask(mask
));
1624 for (i
=0; i
<hi
->ignores
->used
; i
++) {
1625 if (!irccasecmp(new_mask
, hi
->ignores
->list
[i
])) {
1626 reply("NSMSG_ADDIGNORE_ALREADY", new_mask
);
1631 string_list_append(hi
->ignores
, new_mask
);
1632 reply("NSMSG_ADDIGNORE_SUCCESS", new_mask
);
1634 for (target
= hi
->users
; target
; target
= target
->next_authed
) {
1635 irc_silence(target
, new_mask
, 1);
1640 static NICKSERV_FUNC(cmd_addignore
)
1642 NICKSERV_MIN_PARMS(2);
1644 return nickserv_ignore(cmd
, user
, user
->handle_info
, argv
[1]);
1647 static NICKSERV_FUNC(cmd_oaddignore
)
1649 struct handle_info
*hi
;
1651 NICKSERV_MIN_PARMS(3);
1652 if (!(hi
= get_victim_oper(user
, argv
[1])))
1655 return nickserv_ignore(cmd
, user
, hi
, argv
[2]);
1659 nickserv_delignore(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, char *del_mask
)
1662 struct userNode
*target
;
1663 char *pmask
= strdup(pretty_mask(del_mask
));
1664 for (i
=0; i
<hi
->ignores
->used
; i
++) {
1665 if (!strcmp(pmask
, hi
->ignores
->list
[i
]) || !strcmp(del_mask
, hi
->ignores
->list
[i
])) {
1666 char *old_mask
= hi
->ignores
->list
[i
];
1667 hi
->ignores
->list
[i
] = hi
->ignores
->list
[--hi
->ignores
->used
];
1668 reply("NSMSG_DELMASK_SUCCESS", old_mask
);
1669 for (target
= hi
->users
; target
; target
= target
->next_authed
) {
1670 irc_silence(target
, old_mask
, 0);
1677 reply("NSMSG_DELMASK_NOT_FOUND");
1681 static NICKSERV_FUNC(cmd_delignore
)
1683 NICKSERV_MIN_PARMS(2);
1684 return nickserv_delignore(cmd
, user
, user
->handle_info
, argv
[1]);
1687 static NICKSERV_FUNC(cmd_odelignore
)
1689 struct handle_info
*hi
;
1690 NICKSERV_MIN_PARMS(3);
1691 if (!(hi
= get_victim_oper(user
, argv
[1])))
1693 return nickserv_delignore(cmd
, user
, hi
, argv
[2]);
1696 static NICKSERV_FUNC(cmd_handleinfo
)
1699 unsigned int i
, pos
=0, herelen
;
1700 struct userNode
*target
, *next_un
;
1701 struct handle_info
*hi
;
1702 const char *nsmsg_none
;
1705 if (!(hi
= user
->handle_info
)) {
1706 reply("NSMSG_MUST_AUTH");
1709 } else if (!(hi
= modcmd_get_handle_info(user
, argv
[1]))) {
1713 nsmsg_none
= handle_find_message(hi
, "MSG_NONE");
1714 reply("NSMSG_HANDLEINFO_ON", hi
->handle
);
1716 reply("NSMSG_HANDLEINFO_REGGED", ctime(&hi
->registered
));
1719 intervalString(buff
, now
- hi
->lastseen
, user
->handle_info
);
1720 reply("NSMSG_HANDLEINFO_LASTSEEN", buff
);
1722 reply("NSMSG_HANDLEINFO_LASTSEEN_NOW");
1725 reply("NSMSG_HANDLEINFO_INFOLINE", (hi
->infoline
? hi
->infoline
: nsmsg_none
));
1726 if (HANDLE_FLAGGED(hi
, FROZEN
))
1727 reply("NSMSG_HANDLEINFO_VACATION");
1729 if (oper_has_access(user
, cmd
->parent
->bot
, 0, 1)) {
1730 struct do_not_register
*dnr
;
1731 if ((dnr
= chanserv_is_dnr(NULL
, hi
)))
1732 reply("NSMSG_HANDLEINFO_DNR", dnr
->setter
, dnr
->reason
);
1733 if ((user
->handle_info
->opserv_level
< 900) && !oper_outranks(user
, hi
))
1735 } else if (hi
!= user
->handle_info
) {
1736 reply("NSMSG_HANDLEINFO_END");
1741 reply("NSMSG_HANDLEINFO_KARMA", hi
->karma
);
1743 if (nickserv_conf
.email_enabled
)
1744 reply("NSMSG_HANDLEINFO_EMAIL_ADDR", visible_email_addr(user
, hi
));
1748 switch (hi
->cookie
->type
) {
1749 case ACTIVATION
: type
= "NSMSG_HANDLEINFO_COOKIE_ACTIVATION"; break;
1750 case PASSWORD_CHANGE
: type
= "NSMSG_HANDLEINFO_COOKIE_PASSWORD"; break;
1751 case EMAIL_CHANGE
: type
= "NSMSG_HANDLEINFO_COOKIE_EMAIL"; break;
1752 case ALLOWAUTH
: type
= "NSMSG_HANDLEINFO_COOKIE_ALLOWAUTH"; break;
1753 default: type
= "NSMSG_HANDLEINFO_COOKIE_UNKNOWN"; break;
1759 unsigned long flen
= 1;
1760 char flags
[34]; /* 32 bits possible plus '+' and '\0' */
1762 for (i
=0, flen
=1; handle_flags
[i
]; i
++)
1763 if (hi
->flags
& 1 << i
)
1764 flags
[flen
++] = handle_flags
[i
];
1766 reply("NSMSG_HANDLEINFO_FLAGS", flags
);
1768 reply("NSMSG_HANDLEINFO_FLAGS", nsmsg_none
);
1771 if (HANDLE_FLAGGED(hi
, SUPPORT_HELPER
)
1772 || HANDLE_FLAGGED(hi
, NETWORK_HELPER
)
1773 || (hi
->opserv_level
> 0)) {
1774 reply("NSMSG_HANDLEINFO_EPITHET", (hi
->epithet
? hi
->epithet
: nsmsg_none
));
1777 if (IsHelping(user
) || IsOper(user
))
1782 strftime(date
, 64, "%b %d %Y", localtime(&hi
->note
->date
));
1783 reply("NSMSG_HANDLEINFO_NOTE", hi
->note
->setter
, date
, hi
->note
->note
);
1788 reply("NSMSG_HANDLEINFO_FAKEHOST", (hi
->fakehost
? hi
->fakehost
: handle_find_message(hi
, "MSG_NONE")));
1790 if (hi
->last_quit_host
[0])
1791 reply("NSMSG_HANDLEINFO_LAST_HOST", hi
->last_quit_host
);
1793 reply("NSMSG_HANDLEINFO_LAST_HOST_UNKNOWN");
1795 if (nickserv_conf
.disable_nicks
) {
1796 /* nicks disabled; don't show anything about registered nicks */
1797 } else if (hi
->nicks
) {
1798 struct nick_info
*ni
, *next_ni
;
1799 for (ni
= hi
->nicks
; ni
; ni
= next_ni
) {
1800 herelen
= strlen(ni
->nick
);
1801 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1803 goto print_nicks_buff
;
1807 memcpy(buff
+pos
, ni
->nick
, herelen
);
1808 pos
+= herelen
; buff
[pos
++] = ' ';
1812 reply("NSMSG_HANDLEINFO_NICKS", buff
);
1817 reply("NSMSG_HANDLEINFO_NICKS", nsmsg_none
);
1820 if (hi
->masks
->used
) {
1821 for (i
=0; i
< hi
->masks
->used
; i
++) {
1822 herelen
= strlen(hi
->masks
->list
[i
]);
1823 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1825 goto print_mask_buff
;
1827 memcpy(buff
+pos
, hi
->masks
->list
[i
], herelen
);
1828 pos
+= herelen
; buff
[pos
++] = ' ';
1829 if (i
+1 == hi
->masks
->used
) {
1832 reply("NSMSG_HANDLEINFO_MASKS", buff
);
1837 reply("NSMSG_HANDLEINFO_MASKS", nsmsg_none
);
1840 if (hi
->sslfps
->used
) {
1841 for (i
=0; i
< hi
->sslfps
->used
; i
++) {
1842 herelen
= strlen(hi
->sslfps
->list
[i
]);
1843 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1845 goto print_sslfp_buff
;
1847 memcpy(buff
+pos
, hi
->sslfps
->list
[i
], herelen
);
1848 pos
+= herelen
; buff
[pos
++] = ' ';
1849 if (i
+1 == hi
->sslfps
->used
) {
1852 reply("NSMSG_HANDLEINFO_SSLFPS", buff
);
1857 reply("NSMSG_HANDLEINFO_SSLFPS", nsmsg_none
);
1860 if (hi
->ignores
->used
) {
1861 for (i
=0; i
< hi
->ignores
->used
; i
++) {
1862 herelen
= strlen(hi
->ignores
->list
[i
]);
1863 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1865 goto print_ignore_buff
;
1867 memcpy(buff
+pos
, hi
->ignores
->list
[i
], herelen
);
1868 pos
+= herelen
; buff
[pos
++] = ' ';
1869 if (i
+1 == hi
->ignores
->used
) {
1872 reply("NSMSG_HANDLEINFO_IGNORES", buff
);
1877 reply("NSMSG_HANDLEINFO_IGNORES", nsmsg_none
);
1881 struct userData
*chan
, *next
;
1884 for (chan
= hi
->channels
; chan
; chan
= next
) {
1885 next
= chan
->u_next
;
1886 name
= chan
->channel
->channel
->name
;
1887 herelen
= strlen(name
);
1888 if (pos
+ herelen
+ 7 > ArrayLength(buff
)) {
1890 goto print_chans_buff
;
1892 if (IsUserSuspended(chan
))
1894 pos
+= sprintf(buff
+pos
, "%s:%s ", user_level_name_from_level(chan
->access
), name
);
1898 reply("NSMSG_HANDLEINFO_CHANNELS", buff
);
1903 reply("NSMSG_HANDLEINFO_CHANNELS", nsmsg_none
);
1906 for (target
= hi
->users
; target
; target
= next_un
) {
1907 herelen
= strlen(target
->nick
);
1908 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1910 goto print_cnick_buff
;
1912 next_un
= target
->next_authed
;
1914 memcpy(buff
+pos
, target
->nick
, herelen
);
1915 pos
+= herelen
; buff
[pos
++] = ' ';
1919 reply("NSMSG_HANDLEINFO_CURRENT", buff
);
1924 reply("NSMSG_HANDLEINFO_END");
1925 return 1 | ((hi
!= user
->handle_info
) ? CMD_LOG_STAFF
: 0);
1928 static NICKSERV_FUNC(cmd_userinfo
)
1930 struct userNode
*target
;
1932 NICKSERV_MIN_PARMS(2);
1933 if (!(target
= GetUserH(argv
[1]))) {
1934 reply("MSG_NICK_UNKNOWN", argv
[1]);
1937 if (target
->handle_info
)
1938 reply("NSMSG_USERINFO_AUTHED_AS", target
->nick
, target
->handle_info
->handle
);
1940 reply("NSMSG_USERINFO_NOT_AUTHED", target
->nick
);
1944 static NICKSERV_FUNC(cmd_nickinfo
)
1946 struct nick_info
*ni
;
1948 NICKSERV_MIN_PARMS(2);
1949 if (!(ni
= get_nick_info(argv
[1]))) {
1950 reply("MSG_NICK_UNKNOWN", argv
[1]);
1953 reply("NSMSG_NICKINFO_OWNER", ni
->nick
, ni
->owner
->handle
);
1957 static NICKSERV_FUNC(cmd_rename_handle
)
1959 struct handle_info
*hi
;
1960 struct userNode
*uNode
;
1964 NICKSERV_MIN_PARMS(3);
1965 if(nickserv_conf
.force_handles_lowercase
)
1966 irc_strtolower(argv
[2]);
1967 if (!(hi
= get_victim_oper(user
, argv
[1])))
1969 if (!is_valid_handle(argv
[2])) {
1970 reply("NSMSG_FAIL_RENAME", argv
[1], argv
[2]);
1973 if (get_handle_info(argv
[2])) {
1974 reply("NSMSG_HANDLE_EXISTS", argv
[2]);
1977 if(strlen(argv
[2]) > 30)
1979 reply("NMSG_HANDLE_TOLONG", argv
[2], 30);
1983 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1985 if( (rc
= ldap_rename_account(hi
->handle
, argv
[2])) != LDAP_SUCCESS
) {
1986 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
1992 dict_remove2(nickserv_handle_dict
, old_handle
= hi
->handle
, 1);
1993 hi
->handle
= strdup(argv
[2]);
1994 dict_insert(nickserv_handle_dict
, hi
->handle
, hi
);
1995 for (nn
=0; nn
<rf_list_used
; nn
++)
1996 rf_list
[nn
](hi
, old_handle
, rf_list_extra
[nn
]);
1998 if (nickserv_conf
.sync_log
) {
1999 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
2000 irc_rename(uNode
, hi
->handle
);
2002 SyncLog("RENAME %s %s", old_handle
, hi
->handle
);
2005 reply("NSMSG_HANDLE_CHANGED", old_handle
, hi
->handle
);
2006 global_message_args(MESSAGE_RECIPIENT_OPERS
, "NSMSG_ACCOUNT_RENAMED",
2007 user
->handle_info
->handle
, old_handle
, hi
->handle
);
2013 static failpw_func_t
*failpw_func_list
;
2014 static void **failpw_func_list_extra
;
2015 static unsigned int failpw_func_size
= 0, failpw_func_used
= 0;
2018 reg_failpw_func(failpw_func_t func
, void *extra
)
2020 if (failpw_func_used
== failpw_func_size
) {
2021 if (failpw_func_size
) {
2022 failpw_func_size
<<= 1;
2023 failpw_func_list
= realloc(failpw_func_list
, failpw_func_size
*sizeof(failpw_func_t
));
2024 failpw_func_list_extra
= realloc(failpw_func_list_extra
, failpw_func_size
*sizeof(void*));
2026 failpw_func_size
= 8;
2027 failpw_func_list
= malloc(failpw_func_size
*sizeof(failpw_func_t
));
2028 failpw_func_list_extra
= malloc(failpw_func_size
*sizeof(void*));
2031 failpw_func_list
[failpw_func_used
] = func
;
2032 failpw_func_list_extra
[failpw_func_used
++] = extra
;
2036 * Return hi if the handle/pass pair matches, NULL if it doesnt.
2038 * called by nefariouses enhanced AC login-on-connect code
2041 struct handle_info
*loc_auth(char *sslfp
, char *handle
, char *password
, char *userhost
)
2043 int wildmask
= 0, auth
= 0;
2044 int used
, maxlogins
;
2046 struct handle_info
*hi
;
2047 struct userNode
*other
;
2049 int ldap_result
= LDAP_SUCCESS
;
2053 hi
= dict_find(nickserv_handle_dict
, handle
, NULL
);
2056 if (nickserv_conf
.ldap_enable
) {
2057 ldap_result
= ldap_check_auth(handle
, password
);
2058 if (!hi
&& (ldap_result
!= LDAP_SUCCESS
))
2060 if (ldap_result
== LDAP_SUCCESS
) {
2061 /* Mark auth as successful */
2065 if (!hi
&& (ldap_result
== LDAP_SUCCESS
) && nickserv_conf
.ldap_autocreate
) {
2066 /* user not found, but authed to ldap successfully..
2067 * create the account.
2072 /* Add a *@* mask */
2073 /* TODO if userhost is not null, build mask based on that. */
2074 if(nickserv_conf
.default_hostmask
)
2077 return NULL
; /* They dont have a *@* mask so they can't loc */
2079 if(!(hi
= nickserv_register(NULL
, NULL
, handle
, password
, 0))) {
2080 return 0; /* couldn't add the user for some reason */
2083 if((rc
= ldap_get_user_info(handle
, &email
) != LDAP_SUCCESS
))
2085 if(nickserv_conf
.email_required
) {
2090 nickserv_set_email_addr(hi
, email
);
2094 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
2095 string_list_append(hi
->masks
, mask_canonicalized
);
2097 if(nickserv_conf
.sync_log
)
2098 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, "@", handle
);
2103 /* hi should now be a valid handle, if not return NULL */
2108 if (password
&& *password
&& !nickserv_conf
.ldap_enable
) {
2110 if (password
&& *password
) {
2112 if (checkpass(password
, hi
->passwd
))
2116 if (!auth
&& sslfp
&& *sslfp
&& hi
->sslfps
->used
) {
2117 /* If any SSL fingerprint matches, allow it. */
2118 for (ii
=0; ii
<hi
->sslfps
->used
; ii
++) {
2119 if (!irccasecmp(sslfp
, hi
->sslfps
->list
[ii
])) {
2126 /* Auth should have succeeded by this point */
2130 /* We don't know the users hostname, or anything because they
2131 * havn't registered yet. So we can only allow LOC if your
2132 * account has *@* as a hostmask.
2134 * UPDATE: New nefarious LOC supports u@h
2144 buf
= strdup(userhost
);
2145 ident
= mysep(&buf
, "@");
2146 realhost
= mysep(&buf
, ":");
2147 ip
= mysep(&buf
, ":");
2148 if(!ip
|| !realhost
|| !ident
) {
2150 return NULL
; /* Invalid AC request, just quit */
2152 uh
= malloc(strlen(userhost
));
2153 ui
= malloc(strlen(userhost
));
2154 sprintf(uh
, "%s@%s", ident
, realhost
);
2155 sprintf(ui
, "%s@%s", ident
, ip
);
2156 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
2158 if(match_ircglob(uh
, hi
->masks
->list
[ii
])
2159 || match_ircglob(ui
, hi
->masks
->list
[ii
]))
2171 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
2173 if (!strcmp(hi
->masks
->list
[ii
], "*@*"))
2183 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2187 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
2188 for (used
= 0, other
= hi
->users
; other
; other
= other
->next_authed
) {
2189 if (++used
>= maxlogins
) {
2193 /* TODO - Add LOGGING to this function so LOC's are logged.. */
2197 static NICKSERV_FUNC(cmd_auth
)
2199 int pw_arg
, used
, maxlogins
;
2200 struct handle_info
*hi
;
2203 struct userNode
*other
;
2205 int ldap_result
= LDAP_OTHER
;
2209 if (user
->handle_info
) {
2210 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2213 if (IsStamped(user
)) {
2214 /* Unauthenticated users might still have been stamped
2215 previously and could therefore have a hidden host;
2216 do not allow them to authenticate. */
2217 reply("NSMSG_STAMPED_AUTH");
2224 hi
= dict_find(nickserv_handle_dict
, argv
[1], NULL
);
2225 } else if (argc
== 2) {
2228 if (nickserv_conf
.disable_nicks
) {
2229 hi
= get_handle_info(user
->nick
);
2231 /* try to look up their handle from their nick */
2232 /* TODO: handle ldap auth on nickserv style networks, too */
2233 struct nick_info
*ni
;
2234 ni
= get_nick_info(user
->nick
);
2236 reply("NSMSG_NICK_NOT_REGISTERED", user
->nick
);
2242 handle
= hi
->handle
;
2244 handle
= user
->nick
;
2247 reply("MSG_MISSING_PARAMS", argv
[0]);
2248 svccmd_send_help_brief(user
, nickserv
, cmd
);
2253 if(strchr(argv
[1], '<') || strchr(handle
, '>')) {
2254 reply("NSMSG_NO_ANGLEBRACKETS");
2257 if (!is_valid_handle(handle
)) {
2258 reply("NSMSG_BAD_HANDLE", handle
);
2262 if(nickserv_conf
.ldap_enable
) {
2263 ldap_result
= ldap_check_auth(handle
, passwd
);
2264 /* Get the users email address and update it */
2265 if(ldap_result
== LDAP_SUCCESS
) {
2267 if((rc
= ldap_get_user_info(handle
, &email
) != LDAP_SUCCESS
))
2269 if(nickserv_conf
.email_required
) {
2270 reply("NSMSG_LDAP_FAIL_GET_EMAIL", ldap_err2string(rc
));
2275 else if(ldap_result
!= LDAP_INVALID_CREDENTIALS
) {
2276 reply("NSMSG_LDAP_FAIL", ldap_err2string(ldap_result
));
2284 if(nickserv_conf
.ldap_enable
&& ldap_result
== LDAP_SUCCESS
&& nickserv_conf
.ldap_autocreate
) {
2285 /* user not found, but authed to ldap successfully..
2286 * create the account.
2289 if(!(hi
= nickserv_register(user
, user
, argv
[1], argv
[2], 0))) {
2290 reply("NSMSG_UNABLE_TO_ADD");
2291 return 0; /* couldn't add the user for some reason */
2293 /* Add a *@* mask */
2294 if(nickserv_conf
.default_hostmask
)
2297 mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2300 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
2301 string_list_append(hi
->masks
, mask_canonicalized
);
2304 nickserv_set_email_addr(hi
, email
);
2307 if(nickserv_conf
.sync_log
)
2308 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, email
? email
: "@", user
->info
);
2312 reply("NSMSG_HANDLE_NOT_FOUND");
2318 /* Responses from here on look up the language used by the handle they asked about. */
2319 if (!valid_user_for(user
, hi
)) {
2320 if (hi
->email_addr
&& nickserv_conf
.email_enabled
)
2321 send_message_type(4, user
, cmd
->parent
->bot
,
2322 handle_find_message(hi
, "NSMSG_USE_AUTHCOOKIE"),
2325 send_message_type(4, user
, cmd
->parent
->bot
,
2326 handle_find_message(hi
, "NSMSG_HOSTMASK_INVALID"),
2328 argv
[pw_arg
] = "BADMASK";
2332 if(( ( nickserv_conf
.ldap_enable
&& ldap_result
== LDAP_INVALID_CREDENTIALS
) ||
2333 ( (!nickserv_conf
.ldap_enable
) && (!checkpass(passwd
, hi
->passwd
)) ) ) && !valid_user_sslfp(user
, hi
)) {
2335 if (!checkpass(passwd
, hi
->passwd
) && !valid_user_sslfp(user
, hi
)) {
2338 send_message_type(4, user
, cmd
->parent
->bot
,
2339 handle_find_message(hi
, "NSMSG_PASSWORD_INVALID"));
2340 argv
[pw_arg
] = "BADPASS";
2341 for (n
=0; n
<failpw_func_used
; n
++)
2342 failpw_func_list
[n
](user
, hi
, failpw_func_list_extra
[n
]);
2343 if (nickserv_conf
.autogag_enabled
) {
2344 if (!user
->auth_policer
.params
) {
2345 user
->auth_policer
.last_req
= now
;
2346 user
->auth_policer
.params
= nickserv_conf
.auth_policer_params
;
2348 if (!policer_conforms(&user
->auth_policer
, now
, 1.0)) {
2350 hostmask
= generate_hostmask(user
, GENMASK_STRICT_HOST
|GENMASK_BYIP
|GENMASK_NO_HIDING
);
2351 log_module(NS_LOG
, LOG_INFO
, "%s auto-gagged for repeated password guessing.", hostmask
);
2352 gag_create(hostmask
, nickserv
->nick
, "Repeated password guessing.", now
+nickserv_conf
.autogag_duration
);
2354 argv
[pw_arg
] = "GAGGED";
2359 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2360 send_message_type(4, user
, cmd
->parent
->bot
,
2361 handle_find_message(hi
, "NSMSG_HANDLE_SUSPENDED"));
2362 argv
[pw_arg
] = "SUSPENDED";
2365 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
2366 for (used
= 0, other
= hi
->users
; other
; other
= other
->next_authed
) {
2367 if (++used
>= maxlogins
) {
2368 send_message_type(4, user
, cmd
->parent
->bot
,
2369 handle_find_message(hi
, "NSMSG_MAX_LOGINS"),
2371 argv
[pw_arg
] = "MAXLOGINS";
2376 set_user_handle_info(user
, hi
, 1);
2377 if (nickserv_conf
.email_required
&& !hi
->email_addr
)
2378 reply("NSMSG_PLEASE_SET_EMAIL");
2379 if (!is_secure_password(hi
->handle
, passwd
, NULL
))
2380 reply("NSMSG_WEAK_PASSWORD");
2381 if (hi
->passwd
[0] != '$')
2382 cryptpass(passwd
, hi
->passwd
);
2384 /* If a channel was waiting for this user to auth,
2385 * finish adding them */
2386 process_adduser_pending(user
);
2388 reply("NSMSG_AUTH_SUCCESS");
2391 /* Set +x if autohide is on */
2392 if(HANDLE_FLAGGED(hi
, AUTOHIDE
))
2393 irc_umode(user
, "+x");
2395 if (!hi
->masks
->used
) {
2397 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
2398 if (irc_in_addr_is_valid(user
->ip
) && irc_pton(&ip
, NULL
, user
->hostname
))
2399 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_BYIP
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
2402 /* Wipe out the pass for the logs */
2403 argv
[pw_arg
] = "****";
2407 static allowauth_func_t
*allowauth_func_list
;
2408 static void **allowauth_func_list_extra
;
2409 static unsigned int allowauth_func_size
= 0, allowauth_func_used
= 0;
2412 reg_allowauth_func(allowauth_func_t func
, void *extra
)
2414 if (allowauth_func_used
== allowauth_func_size
) {
2415 if (allowauth_func_size
) {
2416 allowauth_func_size
<<= 1;
2417 allowauth_func_list
= realloc(allowauth_func_list
, allowauth_func_size
*sizeof(allowauth_func_t
));
2418 allowauth_func_list_extra
= realloc(allowauth_func_list_extra
, allowauth_func_size
*sizeof(void*));
2420 allowauth_func_size
= 8;
2421 allowauth_func_list
= malloc(allowauth_func_size
*sizeof(allowauth_func_t
));
2422 allowauth_func_list_extra
= malloc(allowauth_func_size
*sizeof(void*));
2425 allowauth_func_list
[allowauth_func_used
] = func
;
2426 allowauth_func_list_extra
[allowauth_func_used
++] = extra
;
2429 static NICKSERV_FUNC(cmd_allowauth
)
2431 struct userNode
*target
;
2432 struct handle_info
*hi
;
2435 NICKSERV_MIN_PARMS(2);
2436 if (!(target
= GetUserH(argv
[1]))) {
2437 reply("MSG_NICK_UNKNOWN", argv
[1]);
2440 if (target
->handle_info
) {
2441 reply("NSMSG_USER_PREV_AUTH", target
->nick
);
2444 if (IsStamped(target
)) {
2445 /* Unauthenticated users might still have been stamped
2446 previously and could therefore have a hidden host;
2447 do not allow them to authenticate to an account. */
2448 reply("NSMSG_USER_PREV_STAMP", target
->nick
);
2453 else if (!(hi
= get_handle_info(argv
[2]))) {
2454 reply("MSG_HANDLE_UNKNOWN", argv
[2]);
2458 if (hi
->opserv_level
> user
->handle_info
->opserv_level
) {
2459 reply("MSG_USER_OUTRANKED", hi
->handle
);
2462 if (((hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
))
2463 || (hi
->opserv_level
> 0))
2464 && ((argc
< 4) || irccasecmp(argv
[3], "staff"))) {
2465 reply("NSMSG_ALLOWAUTH_STAFF", hi
->handle
);
2468 dict_insert(nickserv_allow_auth_dict
, target
->nick
, hi
);
2469 reply("NSMSG_AUTH_ALLOWED", target
->nick
, hi
->handle
);
2470 send_message(target
, nickserv
, "NSMSG_AUTH_ALLOWED_MSG", hi
->handle
, hi
->handle
);
2471 if (nickserv_conf
.email_enabled
)
2472 send_message(target
, nickserv
, "NSMSG_AUTH_ALLOWED_EMAIL");
2474 if (dict_remove(nickserv_allow_auth_dict
, target
->nick
))
2475 reply("NSMSG_AUTH_NORMAL_ONLY", target
->nick
);
2477 reply("NSMSG_AUTH_UNSPECIAL", target
->nick
);
2479 for (n
=0; n
<allowauth_func_used
; n
++)
2480 allowauth_func_list
[n
](user
, target
, hi
, allowauth_func_list_extra
[n
]);
2484 static NICKSERV_FUNC(cmd_authcookie
)
2486 struct handle_info
*hi
;
2488 NICKSERV_MIN_PARMS(2);
2489 if (user
->handle_info
) {
2490 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2493 if (IsStamped(user
)) {
2494 /* Unauthenticated users might still have been stamped
2495 previously and could therefore have a hidden host;
2496 do not allow them to authenticate to an account. */
2497 reply("NSMSG_STAMPED_AUTHCOOKIE");
2500 if (!(hi
= get_handle_info(argv
[1]))) {
2501 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2504 if (!hi
->email_addr
) {
2505 reply("MSG_SET_EMAIL_ADDR");
2508 nickserv_make_cookie(user
, hi
, ALLOWAUTH
, NULL
, 0);
2512 static NICKSERV_FUNC(cmd_delcookie
)
2514 struct handle_info
*hi
;
2516 hi
= user
->handle_info
;
2518 reply("NSMSG_NO_COOKIE");
2521 switch (hi
->cookie
->type
) {
2524 reply("NSMSG_MUST_TIME_OUT");
2527 nickserv_eat_cookie(hi
->cookie
);
2528 reply("NSMSG_ATE_COOKIE");
2534 static NICKSERV_FUNC(cmd_odelcookie
)
2536 struct handle_info
*hi
;
2538 NICKSERV_MIN_PARMS(2);
2540 if (!(hi
= get_victim_oper(user
, argv
[1])))
2544 reply("NSMSG_NO_COOKIE_FOREIGN", hi
->handle
);
2548 switch (hi
->cookie
->type
) {
2550 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2552 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2554 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2555 /* Falied to update password in ldap, but still
2556 * updated it here.. what should we do? */
2557 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2562 if (nickserv_conf
.sync_log
)
2563 SyncLog("ACCOUNTACC %s", hi
->handle
);
2565 case PASSWORD_CHANGE
:
2572 reply("NSMSG_BAD_COOKIE_TYPE", hi
->cookie
->type
);
2573 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d for account %s.", hi
->cookie
->type
, hi
->handle
);
2577 nickserv_eat_cookie(hi
->cookie
);
2578 reply("NSMSG_ATE_FOREIGN_COOKIE", hi
->handle
);
2583 static NICKSERV_FUNC(cmd_resetpass
)
2585 struct handle_info
*hi
;
2586 char crypted
[MD5_CRYPT_LENGTH
];
2589 NICKSERV_MIN_PARMS(3);
2590 if(argc
>= 4 && !strcmp(argv
[3], "WEBLINK"))
2594 if (user
->handle_info
) {
2595 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2598 if (IsStamped(user
)) {
2599 /* Unauthenticated users might still have been stamped
2600 previously and could therefore have a hidden host;
2601 do not allow them to activate an account. */
2602 reply("NSMSG_STAMPED_RESETPASS");
2605 if (!(hi
= get_handle_info(argv
[1]))) {
2606 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2609 if (!hi
->email_addr
) {
2610 reply("MSG_SET_EMAIL_ADDR");
2613 cryptpass(argv
[2], crypted
);
2615 nickserv_make_cookie(user
, hi
, PASSWORD_CHANGE
, crypted
, weblink
);
2619 static NICKSERV_FUNC(cmd_cookie
)
2621 struct handle_info
*hi
;
2624 if ((argc
== 2) && (hi
= user
->handle_info
) && hi
->cookie
&& (hi
->cookie
->type
== EMAIL_CHANGE
)) {
2627 NICKSERV_MIN_PARMS(3);
2628 if (!(hi
= get_handle_info(argv
[1]))) {
2629 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2635 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2636 reply("NSMSG_HANDLE_SUSPENDED");
2641 reply("NSMSG_NO_COOKIE");
2645 /* Check validity of operation before comparing cookie to
2646 * prohibit guessing by authed users. */
2647 if (user
->handle_info
2648 && (hi
->cookie
->type
!= EMAIL_CHANGE
)
2649 && (hi
->cookie
->type
!= PASSWORD_CHANGE
)) {
2650 reply("NSMSG_CANNOT_COOKIE");
2654 if (strcmp(cookie
, hi
->cookie
->cookie
)) {
2655 reply("NSMSG_BAD_COOKIE");
2659 switch (hi
->cookie
->type
) {
2662 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2664 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2665 /* Falied to update email in ldap, but still
2666 * updated it here.. what should we do? */
2667 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2672 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2673 set_user_handle_info(user
, hi
, 1);
2674 reply("NSMSG_HANDLE_ACTIVATED");
2675 if (nickserv_conf
.sync_log
)
2676 SyncLog("ACCOUNTACC %s", hi
->handle
);
2678 case PASSWORD_CHANGE
:
2680 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2682 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2683 /* Falied to update email in ldap, but still
2684 * updated it here.. what should we do? */
2685 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2690 set_user_handle_info(user
, hi
, 1);
2691 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2692 reply("NSMSG_PASSWORD_CHANGED");
2693 if (nickserv_conf
.sync_log
)
2694 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
2698 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2700 if((rc
= ldap_do_modify(hi
->handle
, NULL
, hi
->cookie
->data
)) != LDAP_SUCCESS
) {
2701 /* Falied to update email in ldap, but still
2702 * updated it here.. what should we do? */
2703 reply("NSMSG_LDAP_FAIL_SEND_EMAIL", ldap_err2string(rc
));
2708 if (!hi
->email_addr
&& nickserv_conf
.sync_log
) {
2710 * This should only happen if an OREGISTER was sent. Require
2711 * email must be enabled! - SiRVulcaN
2713 if (nickserv_conf
.sync_log
)
2714 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, hi
->cookie
->data
, user
->info
);
2717 nickserv_set_email_addr(hi
, hi
->cookie
->data
);
2718 reply("NSMSG_EMAIL_CHANGED");
2719 if (nickserv_conf
.sync_log
)
2720 SyncLog("EMAILCHANGE %s %s", hi
->handle
, hi
->cookie
->data
);
2723 char *mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2724 set_user_handle_info(user
, hi
, 1);
2725 nickserv_addmask(user
, hi
, mask
);
2726 reply("NSMSG_AUTH_SUCCESS");
2731 reply("NSMSG_BAD_COOKIE_TYPE", hi
->cookie
->type
);
2732 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d for account %s.", hi
->cookie
->type
, hi
->handle
);
2736 nickserv_eat_cookie(hi
->cookie
);
2738 process_adduser_pending(user
);
2743 static NICKSERV_FUNC(cmd_oregnick
) {
2745 struct handle_info
*target
;
2746 struct nick_info
*ni
;
2748 NICKSERV_MIN_PARMS(3);
2749 if (!(target
= modcmd_get_handle_info(user
, argv
[1])))
2752 if (!is_registerable_nick(nick
)) {
2753 reply("NSMSG_BAD_NICK", nick
);
2756 ni
= dict_find(nickserv_nick_dict
, nick
, NULL
);
2758 reply("NSMSG_NICK_EXISTS", nick
);
2761 register_nick(nick
, target
);
2762 reply("NSMSG_OREGNICK_SUCCESS", nick
, target
->handle
);
2766 static NICKSERV_FUNC(cmd_regnick
) {
2768 struct nick_info
*ni
;
2770 if (!is_registerable_nick(user
->nick
)) {
2771 reply("NSMSG_BAD_NICK", user
->nick
);
2774 /* count their nicks, see if it's too many */
2775 for (n
=0,ni
=user
->handle_info
->nicks
; ni
; n
++,ni
=ni
->next
) ;
2776 if (n
>= nickserv_conf
.nicks_per_handle
) {
2777 reply("NSMSG_TOO_MANY_NICKS");
2780 ni
= dict_find(nickserv_nick_dict
, user
->nick
, NULL
);
2782 reply("NSMSG_NICK_EXISTS", user
->nick
);
2785 register_nick(user
->nick
, user
->handle_info
);
2786 reply("NSMSG_REGNICK_SUCCESS", user
->nick
);
2790 static NICKSERV_FUNC(cmd_pass
)
2792 struct handle_info
*hi
;
2793 char *old_pass
, *new_pass
;
2794 char crypted
[MD5_CRYPT_LENGTH
+1];
2799 NICKSERV_MIN_PARMS(3);
2800 hi
= user
->handle_info
;
2804 if (!is_secure_password(hi
->handle
, new_pass
, user
)) return 0;
2807 if(nickserv_conf
.ldap_enable
) {
2808 ldap_result
= ldap_check_auth(hi
->handle
, old_pass
);
2809 if(ldap_result
!= LDAP_SUCCESS
) {
2810 if(ldap_result
== LDAP_INVALID_CREDENTIALS
)
2811 reply("NSMSG_PASSWORD_INVALID");
2813 reply("NSMSG_LDAP_FAIL", ldap_err2string(ldap_result
));
2818 if (!checkpass(old_pass
, hi
->passwd
)) {
2819 argv
[1] = "BADPASS";
2820 reply("NSMSG_PASSWORD_INVALID");
2823 cryptpass(new_pass
, crypted
);
2825 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2827 if((rc
= ldap_do_modify(hi
->handle
, crypted
, NULL
)) != LDAP_SUCCESS
) {
2828 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2833 //cryptpass(new_pass, hi->passwd);
2834 strcpy(hi
->passwd
, crypted
);
2835 if (nickserv_conf
.sync_log
)
2836 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
2838 reply("NSMSG_PASS_SUCCESS");
2843 nickserv_addmask(struct userNode
*user
, struct handle_info
*hi
, const char *mask
)
2846 char *new_mask
= canonicalize_hostmask(strdup(mask
));
2847 for (i
=0; i
<hi
->masks
->used
; i
++) {
2848 if (!irccasecmp(new_mask
, hi
->masks
->list
[i
])) {
2849 send_message(user
, nickserv
, "NSMSG_ADDMASK_ALREADY", new_mask
);
2854 string_list_append(hi
->masks
, new_mask
);
2855 send_message(user
, nickserv
, "NSMSG_ADDMASK_SUCCESS", new_mask
);
2859 static NICKSERV_FUNC(cmd_addmask
)
2862 char *mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2863 int res
= nickserv_addmask(user
, user
->handle_info
, mask
);
2867 if (!is_gline(argv
[1])) {
2868 reply("NSMSG_MASK_INVALID", argv
[1]);
2871 return nickserv_addmask(user
, user
->handle_info
, argv
[1]);
2875 static NICKSERV_FUNC(cmd_oaddmask
)
2877 struct handle_info
*hi
;
2879 NICKSERV_MIN_PARMS(3);
2880 if (!(hi
= get_victim_oper(user
, argv
[1])))
2882 return nickserv_addmask(user
, hi
, argv
[2]);
2886 nickserv_delmask(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, const char *del_mask
, int force
)
2889 for (i
=0; i
<hi
->masks
->used
; i
++) {
2890 if (!strcmp(del_mask
, hi
->masks
->list
[i
])) {
2891 char *old_mask
= hi
->masks
->list
[i
];
2892 if (hi
->masks
->used
== 1 && !force
) {
2893 reply("NSMSG_DELMASK_NOTLAST");
2896 hi
->masks
->list
[i
] = hi
->masks
->list
[--hi
->masks
->used
];
2897 reply("NSMSG_DELMASK_SUCCESS", old_mask
);
2902 reply("NSMSG_DELMASK_NOT_FOUND");
2906 static NICKSERV_FUNC(cmd_delmask
)
2908 NICKSERV_MIN_PARMS(2);
2909 return nickserv_delmask(cmd
, user
, user
->handle_info
, argv
[1], 0);
2912 static NICKSERV_FUNC(cmd_odelmask
)
2914 struct handle_info
*hi
;
2915 NICKSERV_MIN_PARMS(3);
2916 if (!(hi
= get_victim_oper(user
, argv
[1])))
2918 return nickserv_delmask(cmd
, user
, hi
, argv
[2], 1);
2922 nickserv_addsslfp(struct userNode
*user
, struct handle_info
*hi
, const char *sslfp
)
2925 char *new_sslfp
= strdup(sslfp
);
2926 for (i
=0; i
<hi
->sslfps
->used
; i
++) {
2927 if (!irccasecmp(new_sslfp
, hi
->sslfps
->list
[i
])) {
2928 send_message(user
, nickserv
, "NSMSG_ADDSSLFP_ALREADY", new_sslfp
);
2933 string_list_append(hi
->sslfps
, new_sslfp
);
2934 send_message(user
, nickserv
, "NSMSG_ADDSSLFP_SUCCESS", new_sslfp
);
2938 static NICKSERV_FUNC(cmd_addsslfp
)
2940 NICKSERV_MIN_PARMS((user
->sslfp
? 1 : 2));
2941 if ((argc
< 2) && (user
->sslfp
)) {
2942 int res
= nickserv_addsslfp(user
, user
->handle_info
, user
->sslfp
);
2945 return nickserv_addsslfp(user
, user
->handle_info
, argv
[1]);
2949 static NICKSERV_FUNC(cmd_oaddsslfp
)
2951 struct handle_info
*hi
;
2953 NICKSERV_MIN_PARMS(3);
2954 if (!(hi
= get_victim_oper(user
, argv
[1])))
2956 return nickserv_addsslfp(user
, hi
, argv
[2]);
2960 nickserv_delsslfp(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, const char *del_sslfp
)
2963 for (i
=0; i
<hi
->sslfps
->used
; i
++) {
2964 if (!irccasecmp(del_sslfp
, hi
->sslfps
->list
[i
])) {
2965 char *old_sslfp
= hi
->sslfps
->list
[i
];
2966 hi
->sslfps
->list
[i
] = hi
->sslfps
->list
[--hi
->sslfps
->used
];
2967 reply("NSMSG_DELSSLFP_SUCCESS", old_sslfp
);
2972 reply("NSMSG_DELSSLFP_NOT_FOUND");
2976 static NICKSERV_FUNC(cmd_delsslfp
)
2978 NICKSERV_MIN_PARMS((user
->sslfp
? 1 : 2));
2979 if ((argc
< 2) && (user
->sslfp
)) {
2980 return nickserv_delsslfp(cmd
, user
, user
->handle_info
, user
->sslfp
);
2982 return nickserv_delsslfp(cmd
, user
, user
->handle_info
, argv
[1]);
2986 static NICKSERV_FUNC(cmd_odelsslfp
)
2988 struct handle_info
*hi
;
2989 NICKSERV_MIN_PARMS(3);
2990 if (!(hi
= get_victim_oper(user
, argv
[1])))
2992 return nickserv_delsslfp(cmd
, user
, hi
, argv
[2]);
2996 nickserv_modify_handle_flags(struct userNode
*user
, struct userNode
*bot
, const char *str
, unsigned long *padded
, unsigned long *premoved
) {
2997 unsigned int nn
, add
= 1, pos
;
2998 unsigned long added
, removed
, flag
;
3000 for (added
=removed
=nn
=0; str
[nn
]; nn
++) {
3002 case '+': add
= 1; break;
3003 case '-': add
= 0; break;
3005 if (!(pos
= handle_inverse_flags
[(unsigned char)str
[nn
]])) {
3006 send_message(user
, bot
, "NSMSG_INVALID_FLAG", str
[nn
]);
3009 if (user
&& (user
->handle_info
->opserv_level
< flag_access_levels
[pos
-1])) {
3010 /* cheesy avoidance of looking up the flag name.. */
3011 send_message(user
, bot
, "NSMSG_FLAG_PRIVILEGED", str
[nn
]);
3014 flag
= 1 << (pos
- 1);
3016 added
|= flag
, removed
&= ~flag
;
3018 removed
|= flag
, added
&= ~flag
;
3023 *premoved
= removed
;
3028 nickserv_apply_flags(struct userNode
*user
, struct handle_info
*hi
, const char *flags
)
3030 unsigned long before
, after
, added
, removed
;
3031 struct userNode
*uNode
;
3033 before
= hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
);
3034 if (!nickserv_modify_handle_flags(user
, nickserv
, flags
, &added
, &removed
))
3036 hi
->flags
= (hi
->flags
| added
) & ~removed
;
3037 after
= hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
);
3039 /* Strip helping flag if they're only a support helper and not
3040 * currently in #support. */
3041 if (HANDLE_FLAGGED(hi
, HELPING
) && (after
== HI_FLAG_SUPPORT_HELPER
)) {
3042 struct channelList
*schannels
;
3044 schannels
= chanserv_support_channels();
3045 for (ii
= 0; ii
< schannels
->used
; ++ii
)
3046 if (find_handle_in_channel(schannels
->list
[ii
], hi
, NULL
))
3048 if (ii
== schannels
->used
)
3049 HANDLE_CLEAR_FLAG(hi
, HELPING
);
3052 if (after
&& !before
) {
3053 /* Add user to current helper list. */
3054 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
3055 userList_append(&curr_helpers
, uNode
);
3056 } else if (!after
&& before
) {
3057 /* Remove user from current helper list. */
3058 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
3059 userList_remove(&curr_helpers
, uNode
);
3066 set_list(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, int override
)
3070 char *set_display
[] = {
3071 "INFO", "WIDTH", "TABLEWIDTH", "COLOR", "PRIVMSG", "STYLE",
3072 "EMAIL", "ANNOUNCEMENTS", "AUTOHIDE", "MAXLOGINS", "LANGUAGE",
3073 "FAKEHOST", "TITLE", "EPITHET", "ADVANCED"
3076 reply("NSMSG_SETTING_LIST");
3077 reply("NSMSG_SETTING_LIST_HEADER");
3079 /* Do this so options are presented in a consistent order. */
3080 for (i
= 0; i
< ArrayLength(set_display
); ++i
)
3081 if ((opt
= dict_find(nickserv_opt_dict
, set_display
[i
], NULL
)))
3082 opt(cmd
, user
, hi
, override
, 0, NULL
);
3083 reply("NSMSG_SETTING_LIST_END");
3086 static NICKSERV_FUNC(cmd_set
)
3088 struct handle_info
*hi
;
3091 hi
= user
->handle_info
;
3093 set_list(cmd
, user
, hi
, 0);
3096 if (!(opt
= dict_find(nickserv_opt_dict
, argv
[1], NULL
))) {
3097 reply("NSMSG_INVALID_OPTION", argv
[1]);
3100 return opt(cmd
, user
, hi
, 0, argc
-1, argv
+1);
3103 static NICKSERV_FUNC(cmd_oset
)
3105 struct handle_info
*hi
;
3108 NICKSERV_MIN_PARMS(2);
3110 if (!(hi
= get_victim_oper(user
, argv
[1])))
3114 set_list(cmd
, user
, hi
, 0);
3118 if (!(opt
= dict_find(nickserv_opt_dict
, argv
[2], NULL
))) {
3119 reply("NSMSG_INVALID_OPTION", argv
[2]);
3123 return opt(cmd
, user
, hi
, 1, argc
-2, argv
+2);
3126 static OPTION_FUNC(opt_info
)
3130 if ((argv
[1][0] == '*') && (argv
[1][1] == 0)) {
3132 hi
->infoline
= NULL
;
3134 hi
->infoline
= strdup(unsplit_string(argv
+1, argc
-1, NULL
));
3138 info
= hi
->infoline
? hi
->infoline
: user_find_message(user
, "MSG_NONE");
3139 reply("NSMSG_SET_INFO", info
);
3143 static OPTION_FUNC(opt_width
)
3146 hi
->screen_width
= strtoul(argv
[1], NULL
, 0);
3148 if ((hi
->screen_width
> 0) && (hi
->screen_width
< MIN_LINE_SIZE
))
3149 hi
->screen_width
= MIN_LINE_SIZE
;
3150 else if (hi
->screen_width
> MAX_LINE_SIZE
)
3151 hi
->screen_width
= MAX_LINE_SIZE
;
3153 reply("NSMSG_SET_WIDTH", hi
->screen_width
);
3157 static OPTION_FUNC(opt_tablewidth
)
3160 hi
->table_width
= strtoul(argv
[1], NULL
, 0);
3162 if ((hi
->table_width
> 0) && (hi
->table_width
< MIN_LINE_SIZE
))
3163 hi
->table_width
= MIN_LINE_SIZE
;
3164 else if (hi
->screen_width
> MAX_LINE_SIZE
)
3165 hi
->table_width
= MAX_LINE_SIZE
;
3167 reply("NSMSG_SET_TABLEWIDTH", hi
->table_width
);
3171 static OPTION_FUNC(opt_color
)
3174 if (enabled_string(argv
[1]))
3175 HANDLE_SET_FLAG(hi
, MIRC_COLOR
);
3176 else if (disabled_string(argv
[1]))
3177 HANDLE_CLEAR_FLAG(hi
, MIRC_COLOR
);
3179 reply("MSG_INVALID_BINARY", argv
[1]);
3184 reply("NSMSG_SET_COLOR", user_find_message(user
, HANDLE_FLAGGED(hi
, MIRC_COLOR
) ? "MSG_ON" : "MSG_OFF"));
3188 static OPTION_FUNC(opt_privmsg
)
3191 if (enabled_string(argv
[1]))
3192 HANDLE_SET_FLAG(hi
, USE_PRIVMSG
);
3193 else if (disabled_string(argv
[1]))
3194 HANDLE_CLEAR_FLAG(hi
, USE_PRIVMSG
);
3196 reply("MSG_INVALID_BINARY", argv
[1]);
3201 reply("NSMSG_SET_PRIVMSG", user_find_message(user
, HANDLE_FLAGGED(hi
, USE_PRIVMSG
) ? "MSG_ON" : "MSG_OFF"));
3205 static OPTION_FUNC(opt_autohide
)
3208 if (enabled_string(argv
[1]))
3209 HANDLE_SET_FLAG(hi
, AUTOHIDE
);
3210 else if (disabled_string(argv
[1]))
3211 HANDLE_CLEAR_FLAG(hi
, AUTOHIDE
);
3213 reply("MSG_INVALID_BINARY", argv
[1]);
3218 reply("NSMSG_SET_AUTOHIDE", user_find_message(user
, HANDLE_FLAGGED(hi
, AUTOHIDE
) ? "MSG_ON" : "MSG_OFF"));
3222 static OPTION_FUNC(opt_style
)
3227 if (!irccasecmp(argv
[1], "Clean"))
3228 hi
->userlist_style
= HI_STYLE_CLEAN
;
3229 else if (!irccasecmp(argv
[1], "Advanced"))
3230 hi
->userlist_style
= HI_STYLE_ADVANCED
;
3231 else if (!irccasecmp(argv
[1], "Classic"))
3232 hi
->userlist_style
= HI_STYLE_CLASSIC
;
3233 else /* Default to normal */
3234 hi
->userlist_style
= HI_STYLE_NORMAL
;
3235 } /* TODO: give error if unknow style is chosen */
3237 switch (hi
->userlist_style
) {
3238 case HI_STYLE_ADVANCED
:
3241 case HI_STYLE_CLASSIC
:
3244 case HI_STYLE_CLEAN
:
3247 case HI_STYLE_NORMAL
:
3252 reply("NSMSG_SET_STYLE", style
);
3256 static OPTION_FUNC(opt_announcements
)
3261 if (enabled_string(argv
[1]))
3262 hi
->announcements
= 'y';
3263 else if (disabled_string(argv
[1]))
3264 hi
->announcements
= 'n';
3265 else if (!strcmp(argv
[1], "?") || !irccasecmp(argv
[1], "default"))
3266 hi
->announcements
= '?';
3268 reply("NSMSG_INVALID_ANNOUNCE", argv
[1]);
3273 switch (hi
->announcements
) {
3274 case 'y': choice
= user_find_message(user
, "MSG_ON"); break;
3275 case 'n': choice
= user_find_message(user
, "MSG_OFF"); break;
3276 case '?': choice
= "default"; break;
3277 default: choice
= "unknown"; break;
3279 reply("NSMSG_SET_ANNOUNCEMENTS", choice
);
3283 static OPTION_FUNC(opt_password
)
3285 char crypted
[MD5_CRYPT_LENGTH
+1];
3290 reply("NSMSG_USE_CMD_PASS");
3294 cryptpass(argv
[1], crypted
);
3296 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
3298 if((rc
= ldap_do_modify(hi
->handle
, crypted
, NULL
)) != LDAP_SUCCESS
) {
3299 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3304 strcpy(hi
->passwd
, crypted
);
3305 if (nickserv_conf
.sync_log
)
3306 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
3308 reply("NSMSG_SET_PASSWORD", "***");
3312 static OPTION_FUNC(opt_flags
)
3315 unsigned int ii
, flen
;
3318 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3323 nickserv_apply_flags(user
, hi
, argv
[1]);
3325 for (ii
= flen
= 0; handle_flags
[ii
]; ii
++)
3326 if (hi
->flags
& (1 << ii
))
3327 flags
[flen
++] = handle_flags
[ii
];
3330 reply("NSMSG_SET_FLAGS", flags
);
3332 reply("NSMSG_SET_FLAGS", user_find_message(user
, "MSG_NONE"));
3336 static OPTION_FUNC(opt_email
)
3340 if (!valid_email(argv
[1])) {
3341 reply("NSMSG_BAD_EMAIL_ADDR");
3344 if ((str
= mail_prohibited_address(argv
[1]))) {
3345 reply("NSMSG_EMAIL_PROHIBITED", argv
[1], str
);
3348 if (hi
->email_addr
&& !irccasecmp(hi
->email_addr
, argv
[1]))
3349 reply("NSMSG_EMAIL_SAME");
3351 nickserv_make_cookie(user
, hi
, EMAIL_CHANGE
, argv
[1], 0);
3354 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
3356 if((rc
= ldap_do_modify(hi
->handle
, NULL
, argv
[1])) != LDAP_SUCCESS
) {
3357 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3362 nickserv_set_email_addr(hi
, argv
[1]);
3364 nickserv_eat_cookie(hi
->cookie
);
3365 reply("NSMSG_SET_EMAIL", visible_email_addr(user
, hi
));
3368 reply("NSMSG_SET_EMAIL", visible_email_addr(user
, hi
));
3372 static OPTION_FUNC(opt_maxlogins
)
3374 unsigned char maxlogins
;
3376 maxlogins
= strtoul(argv
[1], NULL
, 0);
3377 if ((maxlogins
> nickserv_conf
.hard_maxlogins
) && !override
) {
3378 reply("NSMSG_BAD_MAX_LOGINS", nickserv_conf
.hard_maxlogins
);
3381 hi
->maxlogins
= maxlogins
;
3383 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
3384 reply("NSMSG_SET_MAXLOGINS", maxlogins
);
3388 static OPTION_FUNC(opt_advanced
)
3391 if (enabled_string(argv
[1]))
3392 HANDLE_SET_FLAG(hi
, ADVANCED
);
3393 else if (disabled_string(argv
[1]))
3394 HANDLE_CLEAR_FLAG(hi
, ADVANCED
);
3396 reply("MSG_INVALID_BINARY", argv
[1]);
3401 reply("NSMSG_SET_ADVANCED", user_find_message(user
, HANDLE_FLAGGED(hi
, ADVANCED
) ? "MSG_ON" : "MSG_OFF"));
3405 static OPTION_FUNC(opt_language
)
3407 struct language
*lang
;
3409 lang
= language_find(argv
[1]);
3410 if (irccasecmp(lang
->name
, argv
[1]))
3411 reply("NSMSG_LANGUAGE_NOT_FOUND", argv
[1], lang
->name
);
3412 hi
->language
= lang
;
3414 reply("NSMSG_SET_LANGUAGE", hi
->language
->name
);
3418 static OPTION_FUNC(opt_karma
)
3421 send_message(user
, nickserv
, "MSG_SETTING_PRIVILEGED", argv
[0]);
3426 if (argv
[1][0] == '+' && isdigit(argv
[1][1])) {
3427 hi
->karma
+= strtoul(argv
[1] + 1, NULL
, 10);
3428 } else if (argv
[1][0] == '-' && isdigit(argv
[1][1])) {
3429 hi
->karma
-= strtoul(argv
[1] + 1, NULL
, 10);
3431 send_message(user
, nickserv
, "NSMSG_INVALID_KARMA", argv
[1]);
3435 send_message(user
, nickserv
, "NSMSG_SET_KARMA", hi
->karma
);
3439 /* Called from opserv from cmd_access */
3441 oper_try_set_access(struct userNode
*user
, struct userNode
*bot
, struct handle_info
*target
, unsigned int new_level
) {
3442 if (!oper_has_access(user
, bot
, nickserv_conf
.modoper_level
, 0))
3444 if ((user
->handle_info
->opserv_level
< target
->opserv_level
)
3445 || ((user
->handle_info
->opserv_level
== target
->opserv_level
)
3446 && (user
->handle_info
->opserv_level
< 1000))) {
3447 send_message(user
, bot
, "MSG_USER_OUTRANKED", target
->handle
);
3450 if ((user
->handle_info
->opserv_level
< new_level
)
3451 || ((user
->handle_info
->opserv_level
== new_level
)
3452 && (user
->handle_info
->opserv_level
< 1000))) {
3453 send_message(user
, bot
, "NSMSG_OPSERV_LEVEL_BAD");
3456 if (user
->handle_info
== target
) {
3457 send_message(user
, bot
, "MSG_STUPID_ACCESS_CHANGE");
3461 if(nickserv_conf
.ldap_enable
&& *(nickserv_conf
.ldap_oper_group_dn
) && *(nickserv_conf
.ldap_admin_dn
)) {
3463 if(new_level
> nickserv_conf
.ldap_oper_group_level
)
3464 rc
= ldap_add2group(target
->handle
, nickserv_conf
.ldap_oper_group_dn
);
3466 rc
= ldap_delfromgroup(target
->handle
, nickserv_conf
.ldap_oper_group_dn
);
3467 if(rc
!= LDAP_SUCCESS
&& rc
!= LDAP_TYPE_OR_VALUE_EXISTS
&& rc
!= LDAP_NO_SUCH_ATTRIBUTE
) {
3468 send_message(user
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3472 if(nickserv_conf
.ldap_enable
&& *(nickserv_conf
.ldap_field_oslevel
) && *(nickserv_conf
.ldap_admin_dn
)) {
3474 if((rc
= ldap_do_oslevel(target
->handle
, new_level
, target
->opserv_level
)) != LDAP_SUCCESS
) {
3475 send_message(user
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3480 if (target
->opserv_level
== new_level
)
3482 log_module(NS_LOG
, LOG_INFO
, "Account %s setting oper level for account %s to %d (from %d).",
3483 user
->handle_info
->handle
, target
->handle
, new_level
, target
->opserv_level
);
3484 target
->opserv_level
= new_level
;
3488 static OPTION_FUNC(opt_level
)
3493 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3497 res
= (argc
> 1) ? oper_try_set_access(user
, nickserv
, hi
, strtoul(argv
[1], NULL
, 0)) : 0;
3498 reply("NSMSG_SET_LEVEL", hi
->opserv_level
);
3502 static OPTION_FUNC(opt_epithet
)
3504 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_epithet_level
, 0)) {
3506 struct userNode
*target
, *next_un
;
3509 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3513 epithet
= unsplit_string(argv
+1, argc
-1, NULL
);
3517 if ((epithet
[0] == '*') && !epithet
[1])
3520 hi
->epithet
= strdup(epithet
);
3522 for (target
= hi
->users
; target
; target
= next_un
) {
3523 irc_swhois(nickserv
, target
, hi
->epithet
);
3525 next_un
= target
->next_authed
;
3530 reply("NSMSG_SET_EPITHET", hi
->epithet
);
3532 reply("NSMSG_SET_EPITHET", user_find_message(user
, "MSG_NONE"));
3536 static OPTION_FUNC(opt_title
)
3542 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_title_level
, 0)) {
3544 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3549 if(!strcmp(title
, "*")) {
3551 hi
->fakehost
= NULL
;
3554 if (strchr(title
, '.')) {
3555 reply("NSMSG_TITLE_INVALID");
3558 /* Alphanumeric titles only. */
3559 for(sptr
= title
; *sptr
; sptr
++) {
3560 if(!isalnum(*sptr
) && *sptr
!= '-') {
3561 reply("NSMSG_TITLE_INVALID");
3565 if ((strlen(user
->handle_info
->handle
) + strlen(title
) +
3566 strlen(nickserv_conf
.titlehost_suffix
) + 2) > HOSTLEN
) {
3567 reply("NSMSG_TITLE_TRUNCATED");
3571 hi
->fakehost
= malloc(strlen(title
)+2);
3572 hi
->fakehost
[0] = '.';
3573 strcpy(hi
->fakehost
+1, title
);
3576 } else if (hi
->fakehost
&& (hi
->fakehost
[0] == '.'))
3577 title
= hi
->fakehost
+ 1;
3579 /* If theres no title set then the default title will therefore
3580 be the first part of hidden_host in x3.conf, so for
3581 consistency with opt_fakehost we will print this here.
3582 This isnt actually used in P10, its just handled to keep from crashing... */
3583 char *hs
, *hidden_suffix
, *rest
;
3585 hs
= conf_get_data("server/hidden_host", RECDB_QSTRING
);
3586 hidden_suffix
= strdup(hs
);
3588 /* Yes we do this twice */
3589 if((rest
= strchr(hidden_suffix
, '.')))
3592 title
= hidden_suffix
;
3596 /* A lame default if someone configured hidden_host to something lame */
3597 title
= strdup("users");
3598 free(hidden_suffix
);
3604 none
= user_find_message(user
, "MSG_NONE");
3605 send_message(user
, nickserv
, "NSMSG_SET_TITLE", title
? title
: none
);
3610 check_vhost(char *vhost
, struct userNode
*user
, struct svccmd
*cmd
)
3614 // check for a dot in the vhost
3615 if(strchr(vhost
, '.') == NULL
) {
3616 reply("NSMSG_NOT_VALID_FAKEHOST_DOT", vhost
);
3620 // check for a @ in the vhost
3621 if(strchr(vhost
, '@') != NULL
) {
3622 reply("NSMSG_NOT_VALID_FAKEHOST_AT", vhost
);
3626 // check for denied words, inspired by monk at paki.sex
3627 for(y
= 0; y
< nickserv_conf
.denied_fakehost_words
->used
; y
++) {
3628 if(strstr(vhost
, nickserv_conf
.denied_fakehost_words
->list
[y
]) != NULL
) {
3629 reply("NSMSG_DENIED_FAKEHOST_WORD", vhost
, nickserv_conf
.denied_fakehost_words
->list
[y
]);
3634 // check for ircu's HOSTLEN length.
3635 if(strlen(vhost
) >= HOSTLEN
) {
3636 reply("NSMSG_NOT_VALID_FAKEHOST_LEN", vhost
);
3640 /* This can be handled by the regex now if desired.
3641 if (vhost[strspn(vhost, "0123456789.")]) {
3642 hostname = vhost + strlen(vhost);
3643 for (depth = 1; depth && (hostname > vhost); depth--) {
3645 while ((hostname > vhost) && (*hostname != '.')) hostname--;
3648 if (*hostname == '.') hostname++; * advance past last dot we saw *
3649 if(strlen(hostname) > 4) {
3650 reply("NSMSG_NOT_VALID_FAKEHOST_TLD_LEN", vhost);
3655 /* test either regex or as valid handle */
3656 if (nickserv_conf
.valid_fakehost_regex_set
) {
3657 int err
= regexec(&nickserv_conf
.valid_fakehost_regex
, vhost
, 0, 0, 0);
3660 buff
[regerror(err
, &nickserv_conf
.valid_fakehost_regex
, buff
, sizeof(buff
))] = 0;
3661 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
3663 if(err
== REG_NOMATCH
) {
3664 reply("NSMSG_NOT_VALID_FAKEHOST_REGEX", vhost
);
3673 static OPTION_FUNC(opt_fakehost
)
3677 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_fakehost_level
, 0)) {
3679 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3684 if ((strlen(fake
) > HOSTLEN
) || (fake
[0] == '.')) {
3685 reply("NSMSG_FAKEHOST_INVALID", HOSTLEN
);
3688 if (!strcmp(fake
, "*")) {
3691 hi
->fakehost
= NULL
;
3694 else if (!check_vhost(argv
[1], user
, cmd
)) {
3695 /* check_vhost takes care of error reply */
3701 hi
->fakehost
= strdup(fake
);
3704 fake
= hi
->fakehost
;
3706 fake
= generate_fakehost(hi
);
3708 /* Tell them we set the host */
3710 fake
= user_find_message(user
, "MSG_NONE");
3711 reply("NSMSG_SET_FAKEHOST", fake
);
3715 static OPTION_FUNC(opt_note
)
3718 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3723 char *text
= unsplit_string(argv
+ 1, argc
- 1, NULL
);
3728 if ((text
[0] == '*') && !text
[1])
3731 if (!(hi
->note
= nickserv_add_note(user
->handle_info
->handle
, now
, text
)))
3736 reply("NSMSG_SET_NOTE", hi
->note
? hi
->note
->note
: user_find_message(user
, "MSG_NONE"));
3740 static NICKSERV_FUNC(cmd_reclaim
)
3742 struct handle_info
*hi
;
3743 struct nick_info
*ni
;
3744 struct userNode
*victim
;
3746 NICKSERV_MIN_PARMS(2);
3747 hi
= user
->handle_info
;
3748 ni
= dict_find(nickserv_nick_dict
, argv
[1], 0);
3750 reply("NSMSG_UNKNOWN_NICK", argv
[1]);
3753 if (ni
->owner
!= user
->handle_info
) {
3754 reply("NSMSG_NOT_YOUR_NICK", ni
->nick
);
3757 victim
= GetUserH(ni
->nick
);
3759 reply("MSG_NICK_UNKNOWN", ni
->nick
);
3762 if (victim
== user
) {
3763 reply("NSMSG_NICK_USER_YOU");
3766 nickserv_reclaim(victim
, ni
, nickserv_conf
.reclaim_action
);
3767 switch (nickserv_conf
.reclaim_action
) {
3768 case RECLAIM_NONE
: reply("NSMSG_RECLAIMED_NONE"); break;
3769 case RECLAIM_WARN
: reply("NSMSG_RECLAIMED_WARN", victim
->nick
); break;
3770 case RECLAIM_SVSNICK
: reply("NSMSG_RECLAIMED_SVSNICK", victim
->nick
); break;
3771 case RECLAIM_KILL
: reply("NSMSG_RECLAIMED_KILL", victim
->nick
); break;
3776 static NICKSERV_FUNC(cmd_unregnick
)
3779 struct handle_info
*hi
;
3780 struct nick_info
*ni
;
3782 hi
= user
->handle_info
;
3783 nick
= (argc
< 2) ? user
->nick
: (const char*)argv
[1];
3784 ni
= dict_find(nickserv_nick_dict
, nick
, NULL
);
3786 reply("NSMSG_UNKNOWN_NICK", nick
);
3789 if (hi
!= ni
->owner
) {
3790 reply("NSMSG_NOT_YOUR_NICK", nick
);
3793 reply("NSMSG_UNREGNICK_SUCCESS", ni
->nick
);
3798 static NICKSERV_FUNC(cmd_ounregnick
)
3800 struct nick_info
*ni
;
3802 NICKSERV_MIN_PARMS(2);
3803 if (!(ni
= get_nick_info(argv
[1]))) {
3804 reply("NSMSG_NICK_NOT_REGISTERED", argv
[1]);
3807 if (!oper_outranks(user
, ni
->owner
))
3809 reply("NSMSG_UNREGNICK_SUCCESS", ni
->nick
);
3814 static NICKSERV_FUNC(cmd_unregister
)
3816 struct handle_info
*hi
;
3819 NICKSERV_MIN_PARMS(2);
3820 hi
= user
->handle_info
;
3823 if (checkpass(passwd
, hi
->passwd
)) {
3824 if(nickserv_unregister_handle(hi
, user
, cmd
->parent
->bot
))
3829 log_module(NS_LOG
, LOG_INFO
, "Account '%s' tried to unregister with the wrong password.", hi
->handle
);
3830 reply("NSMSG_PASSWORD_INVALID");
3835 static NICKSERV_FUNC(cmd_ounregister
)
3837 struct handle_info
*hi
;
3838 char reason
[MAXLEN
];
3841 NICKSERV_MIN_PARMS(2);
3842 if (!(hi
= get_victim_oper(user
, argv
[1])))
3845 if (HANDLE_FLAGGED(hi
, NODELETE
)) {
3846 reply("NSMSG_UNREGISTER_NODELETE", hi
->handle
);
3850 force
= IsOper(user
) && (argc
> 2) && !irccasecmp(argv
[2], "force");
3852 ((hi
->flags
& nickserv_conf
.ounregister_flags
)
3854 || (hi
->last_quit_host
[0] && ((unsigned)(now
- hi
->lastseen
) < nickserv_conf
.ounregister_inactive
)))) {
3855 reply((IsOper(user
) ? "NSMSG_UNREGISTER_MUST_FORCE" : "NSMSG_UNREGISTER_CANNOT_FORCE"), hi
->handle
);
3858 snprintf(reason
, sizeof(reason
), "%s unregistered account %s.", user
->handle_info
->handle
, hi
->handle
);
3859 global_message(MESSAGE_RECIPIENT_STAFF
, reason
);
3860 if(nickserv_unregister_handle(hi
, user
, cmd
->parent
->bot
))
3866 static NICKSERV_FUNC(cmd_status
)
3868 if (nickserv_conf
.disable_nicks
) {
3869 reply("NSMSG_GLOBAL_STATS_NONICK",
3870 dict_size(nickserv_handle_dict
));
3872 if (user
->handle_info
) {
3874 struct nick_info
*ni
;
3875 for (ni
=user
->handle_info
->nicks
; ni
; ni
=ni
->next
) cnt
++;
3876 reply("NSMSG_HANDLE_STATS", cnt
);
3878 reply("NSMSG_HANDLE_NONE");
3880 reply("NSMSG_GLOBAL_STATS",
3881 dict_size(nickserv_handle_dict
),
3882 dict_size(nickserv_nick_dict
));
3887 static NICKSERV_FUNC(cmd_ghost
)
3889 struct userNode
*target
;
3890 char reason
[MAXLEN
];
3892 NICKSERV_MIN_PARMS(2);
3893 if (!(target
= GetUserH(argv
[1]))) {
3894 reply("MSG_NICK_UNKNOWN", argv
[1]);
3897 if (target
== user
) {
3898 reply("NSMSG_CANNOT_GHOST_SELF");
3901 if (!target
->handle_info
|| (target
->handle_info
!= user
->handle_info
)) {
3902 reply("NSMSG_CANNOT_GHOST_USER", target
->nick
);
3905 snprintf(reason
, sizeof(reason
), "Ghost kill on account %s (requested by %s).", target
->handle_info
->handle
, user
->nick
);
3906 DelUser(target
, nickserv
, 1, reason
);
3907 reply("NSMSG_GHOST_KILLED", argv
[1]);
3911 static NICKSERV_FUNC(cmd_vacation
)
3913 HANDLE_SET_FLAG(user
->handle_info
, FROZEN
);
3914 reply("NSMSG_ON_VACATION");
3919 nickserv_saxdb_write(struct saxdb_context
*ctx
) {
3921 struct handle_info
*hi
;
3924 for (it
= dict_first(nickserv_handle_dict
); it
; it
= iter_next(it
)) {
3926 saxdb_start_record(ctx
, iter_key(it
), 0);
3927 if (hi
->announcements
!= '?') {
3928 flags
[0] = hi
->announcements
;
3930 saxdb_write_string(ctx
, KEY_ANNOUNCEMENTS
, flags
);
3933 struct handle_cookie
*cookie
= hi
->cookie
;
3936 switch (cookie
->type
) {
3937 case ACTIVATION
: type
= KEY_ACTIVATION
; break;
3938 case PASSWORD_CHANGE
: type
= KEY_PASSWORD_CHANGE
; break;
3939 case EMAIL_CHANGE
: type
= KEY_EMAIL_CHANGE
; break;
3940 case ALLOWAUTH
: type
= KEY_ALLOWAUTH
; break;
3941 default: type
= NULL
; break;
3944 saxdb_start_record(ctx
, KEY_COOKIE
, 0);
3945 saxdb_write_string(ctx
, KEY_COOKIE_TYPE
, type
);
3946 saxdb_write_int(ctx
, KEY_COOKIE_EXPIRES
, cookie
->expires
);
3948 saxdb_write_string(ctx
, KEY_COOKIE_DATA
, cookie
->data
);
3949 saxdb_write_string(ctx
, KEY_COOKIE
, cookie
->cookie
);
3950 saxdb_end_record(ctx
);
3954 saxdb_write_string(ctx
, KEY_EMAIL_ADDR
, hi
->email_addr
);
3956 saxdb_write_string(ctx
, KEY_EPITHET
, hi
->epithet
);
3958 saxdb_start_record(ctx
, KEY_NOTE_NOTE
, 0);
3959 saxdb_write_string(ctx
, KEY_NOTE_SETTER
, hi
->note
->setter
);
3960 saxdb_write_int(ctx
, KEY_NOTE_DATE
, hi
->note
->date
);
3961 saxdb_write_string(ctx
, KEY_NOTE_NOTE
, hi
->note
->note
);
3962 saxdb_end_record(ctx
);
3966 saxdb_write_string(ctx
, KEY_FAKEHOST
, hi
->fakehost
);
3970 for (ii
=flen
=0; handle_flags
[ii
]; ++ii
)
3971 if (hi
->flags
& (1 << ii
))
3972 flags
[flen
++] = handle_flags
[ii
];
3974 saxdb_write_string(ctx
, KEY_FLAGS
, flags
);
3977 saxdb_write_string(ctx
, KEY_INFO
, hi
->infoline
);
3978 if (hi
->last_quit_host
[0])
3979 saxdb_write_string(ctx
, KEY_LAST_QUIT_HOST
, hi
->last_quit_host
);
3980 saxdb_write_int(ctx
, KEY_LAST_SEEN
, hi
->lastseen
);
3982 saxdb_write_sint(ctx
, KEY_KARMA
, hi
->karma
);
3983 if (hi
->masks
->used
)
3984 saxdb_write_string_list(ctx
, KEY_MASKS
, hi
->masks
);
3985 if (hi
->sslfps
->used
)
3986 saxdb_write_string_list(ctx
, KEY_SSLFPS
, hi
->sslfps
);
3987 if (hi
->ignores
->used
)
3988 saxdb_write_string_list(ctx
, KEY_IGNORES
, hi
->ignores
);
3990 saxdb_write_int(ctx
, KEY_MAXLOGINS
, hi
->maxlogins
);
3992 struct string_list
*slist
;
3993 struct nick_info
*ni
;
3995 slist
= alloc_string_list(nickserv_conf
.nicks_per_handle
);
3996 for (ni
= hi
->nicks
; ni
; ni
= ni
->next
) string_list_append(slist
, ni
->nick
);
3997 saxdb_write_string_list(ctx
, KEY_NICKS
, slist
);
4001 if (hi
->opserv_level
)
4002 saxdb_write_int(ctx
, KEY_OPSERV_LEVEL
, hi
->opserv_level
);
4003 if (hi
->language
!= lang_C
)
4004 saxdb_write_string(ctx
, KEY_LANGUAGE
, hi
->language
->name
);
4005 saxdb_write_string(ctx
, KEY_PASSWD
, hi
->passwd
);
4006 saxdb_write_int(ctx
, KEY_REGISTER_ON
, hi
->registered
);
4007 if (hi
->screen_width
)
4008 saxdb_write_int(ctx
, KEY_SCREEN_WIDTH
, hi
->screen_width
);
4009 if (hi
->table_width
)
4010 saxdb_write_int(ctx
, KEY_TABLE_WIDTH
, hi
->table_width
);
4011 flags
[0] = hi
->userlist_style
;
4013 saxdb_write_string(ctx
, KEY_USERLIST_STYLE
, flags
);
4014 saxdb_end_record(ctx
);
4020 static handle_merge_func_t
*handle_merge_func_list
;
4021 static void **handle_merge_func_list_extra
;
4022 static unsigned int handle_merge_func_size
= 0, handle_merge_func_used
= 0;
4025 reg_handle_merge_func(handle_merge_func_t func
, void *extra
)
4027 if (handle_merge_func_used
== handle_merge_func_size
) {
4028 if (handle_merge_func_size
) {
4029 handle_merge_func_size
<<= 1;
4030 handle_merge_func_list
= realloc(handle_merge_func_list
, handle_merge_func_size
*sizeof(handle_merge_func_t
));
4031 handle_merge_func_list_extra
= realloc(handle_merge_func_list_extra
, handle_merge_func_size
*sizeof(void*));
4033 handle_merge_func_size
= 8;
4034 handle_merge_func_list
= malloc(handle_merge_func_size
*sizeof(handle_merge_func_t
));
4035 handle_merge_func_list_extra
= malloc(handle_merge_func_size
*sizeof(void*));
4038 handle_merge_func_list
[handle_merge_func_used
] = func
;
4039 handle_merge_func_list_extra
[handle_merge_func_used
++] = extra
;
4042 static NICKSERV_FUNC(cmd_merge
)
4044 struct handle_info
*hi_from
, *hi_to
;
4045 struct userNode
*last_user
;
4046 struct userData
*cList
, *cListNext
;
4047 unsigned int ii
, jj
, n
;
4049 NICKSERV_MIN_PARMS(3);
4051 if (!(hi_from
= get_victim_oper(user
, argv
[1])))
4053 if (!(hi_to
= get_victim_oper(user
, argv
[2])))
4055 if (hi_to
== hi_from
) {
4056 reply("NSMSG_CANNOT_MERGE_SELF", hi_to
->handle
);
4060 for (n
=0; n
<handle_merge_func_used
; n
++)
4061 handle_merge_func_list
[n
](user
, hi_to
, hi_from
, handle_merge_func_list_extra
[n
]);
4063 /* Append "from" handle's nicks to "to" handle's nick list. */
4065 struct nick_info
*last_ni
;
4066 for (last_ni
=hi_to
->nicks
; last_ni
->next
; last_ni
=last_ni
->next
) ;
4067 last_ni
->next
= hi_from
->nicks
;
4069 while (hi_from
->nicks
) {
4070 hi_from
->nicks
->owner
= hi_to
;
4071 hi_from
->nicks
= hi_from
->nicks
->next
;
4074 /* Merge the hostmasks. */
4075 for (ii
=0; ii
<hi_from
->masks
->used
; ii
++) {
4076 char *mask
= hi_from
->masks
->list
[ii
];
4077 for (jj
=0; jj
<hi_to
->masks
->used
; jj
++)
4078 if (match_ircglobs(hi_to
->masks
->list
[jj
], mask
))
4080 if (jj
==hi_to
->masks
->used
) /* Nothing from the "to" handle covered this mask, so add it. */
4081 string_list_append(hi_to
->masks
, strdup(mask
));
4084 /* Merge the SSL fingerprints. */
4085 for (ii
=0; ii
<hi_from
->sslfps
->used
; ii
++) {
4086 char *sslfp
= hi_from
->sslfps
->list
[ii
];
4087 for (jj
=0; jj
<hi_to
->sslfps
->used
; jj
++)
4088 if (!irccasecmp(hi_to
->sslfps
->list
[jj
], sslfp
))
4090 if (jj
==hi_to
->sslfps
->used
) /* Nothing from the "to" handle covered this sslfp, so add it. */
4091 string_list_append(hi_to
->sslfps
, strdup(sslfp
));
4094 /* Merge the ignores. */
4095 for (ii
=0; ii
<hi_from
->ignores
->used
; ii
++) {
4096 char *ignore
= hi_from
->ignores
->list
[ii
];
4097 for (jj
=0; jj
<hi_to
->ignores
->used
; jj
++)
4098 if (match_ircglobs(hi_to
->ignores
->list
[jj
], ignore
))
4100 if (jj
==hi_to
->ignores
->used
) /* Nothing from the "to" handle covered this mask, so add it. */
4101 string_list_append(hi_to
->ignores
, strdup(ignore
));
4104 /* Merge the lists of authed users. */
4106 for (last_user
=hi_to
->users
; last_user
->next_authed
; last_user
=last_user
->next_authed
) ;
4107 last_user
->next_authed
= hi_from
->users
;
4109 hi_to
->users
= hi_from
->users
;
4111 /* Repoint the old "from" handle's users. */
4112 for (last_user
=hi_from
->users
; last_user
; last_user
=last_user
->next_authed
) {
4113 last_user
->handle_info
= hi_to
;
4115 hi_from
->users
= NULL
;
4117 /* Merge channel userlists. */
4118 for (cList
=hi_from
->channels
; cList
; cList
=cListNext
) {
4119 struct userData
*cList2
;
4120 cListNext
= cList
->u_next
;
4121 for (cList2
=hi_to
->channels
; cList2
; cList2
=cList2
->u_next
)
4122 if (cList
->channel
== cList2
->channel
)
4124 if (cList2
&& (cList2
->access
>= cList
->access
)) {
4125 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
);
4126 /* keep cList2 in hi_to; remove cList from hi_from */
4127 del_channel_user(cList
, 1);
4130 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
);
4131 /* remove the lower-ranking cList2 from hi_to */
4132 del_channel_user(cList2
, 1);
4134 log_module(NS_LOG
, LOG_INFO
, "Merge: %s had no access in %s", hi_to
->handle
, cList
->channel
->channel
->name
);
4136 /* cList needs to be moved from hi_from to hi_to */
4137 cList
->handle
= hi_to
;
4138 /* Remove from linked list for hi_from */
4139 assert(!cList
->u_prev
);
4140 hi_from
->channels
= cList
->u_next
;
4142 cList
->u_next
->u_prev
= cList
->u_prev
;
4143 /* Add to linked list for hi_to */
4144 cList
->u_prev
= NULL
;
4145 cList
->u_next
= hi_to
->channels
;
4146 if (hi_to
->channels
)
4147 hi_to
->channels
->u_prev
= cList
;
4148 hi_to
->channels
= cList
;
4152 /* Do they get an OpServ level promotion? */
4153 if (hi_from
->opserv_level
> hi_to
->opserv_level
)
4154 hi_to
->opserv_level
= hi_from
->opserv_level
;
4156 /* What about last seen time? */
4157 if (hi_from
->lastseen
> hi_to
->lastseen
)
4158 hi_to
->lastseen
= hi_from
->lastseen
;
4160 /* New karma is the sum of the two original karmas. */
4161 hi_to
->karma
+= hi_from
->karma
;
4163 /* Does a fakehost carry over? (This intentionally doesn't set it
4164 * for users previously attached to hi_to. They'll just have to
4167 if (hi_from
->fakehost
&& !hi_to
->fakehost
)
4168 hi_to
->fakehost
= strdup(hi_from
->fakehost
);
4170 /* Notify of success. */
4171 reply("NSMSG_HANDLES_MERGED", hi_from
->handle
, hi_to
->handle
);
4172 global_message_args(MESSAGE_RECIPIENT_OPERS
, "NSMSG_ACCOUNT_MERGED", user
->nick
,
4173 user
->handle_info
->handle
, hi_from
->handle
, hi_to
->handle
);
4175 /* Unregister the "from" handle. */
4176 nickserv_unregister_handle(hi_from
, NULL
, cmd
->parent
->bot
);
4177 /* TODO: fix it so that if the ldap delete in nickserv_unregister_handle fails,
4178 * the process isn't completed.
4184 struct nickserv_discrim
{
4185 unsigned long flags_on
, flags_off
;
4186 time_t min_registered
, max_registered
;
4189 int min_level
, max_level
;
4190 int min_karma
, max_karma
;
4191 enum { SUBSET
, EXACT
, SUPERSET
, LASTQUIT
} hostmask_type
;
4192 const char *nickmask
;
4193 const char *hostmask
;
4194 const char *handlemask
;
4195 const char *emailmask
;
4197 unsigned int inldap
;
4201 typedef void (*discrim_search_func
)(struct userNode
*source
, struct handle_info
*hi
);
4203 struct discrim_apply_info
{
4204 struct nickserv_discrim
*discrim
;
4205 discrim_search_func func
;
4206 struct userNode
*source
;
4207 unsigned int matched
;
4210 static struct nickserv_discrim
*
4211 nickserv_discrim_create(struct svccmd
*cmd
, struct userNode
*user
, unsigned int argc
, char *argv
[])
4214 struct nickserv_discrim
*discrim
;
4216 discrim
= malloc(sizeof(*discrim
));
4217 memset(discrim
, 0, sizeof(*discrim
));
4218 discrim
->min_level
= 0;
4219 discrim
->max_level
= INT_MAX
;
4220 discrim
->limit
= 50;
4221 discrim
->min_registered
= 0;
4222 discrim
->max_registered
= INT_MAX
;
4223 discrim
->lastseen
= LONG_MAX
;
4224 discrim
->min_karma
= INT_MIN
;
4225 discrim
->max_karma
= INT_MAX
;
4227 discrim
->inldap
= 2;
4230 for (i
=0; i
<argc
; i
++) {
4231 if (i
== argc
- 1) {
4232 reply("MSG_MISSING_PARAMS", argv
[i
]);
4235 if (!irccasecmp(argv
[i
], "limit")) {
4236 discrim
->limit
= strtoul(argv
[++i
], NULL
, 0);
4237 } else if (!irccasecmp(argv
[i
], "flags")) {
4238 nickserv_modify_handle_flags(user
, nickserv
, argv
[++i
], &discrim
->flags_on
, &discrim
->flags_off
);
4239 } else if (!irccasecmp(argv
[i
], "registered")) {
4240 const char *cmp
= argv
[++i
];
4241 if (cmp
[0] == '<') {
4242 if (cmp
[1] == '=') {
4243 discrim
->min_registered
= now
- ParseInterval(cmp
+2);
4245 discrim
->min_registered
= now
- ParseInterval(cmp
+1) + 1;
4247 } else if (cmp
[0] == '=') {
4248 discrim
->min_registered
= discrim
->max_registered
= now
- ParseInterval(cmp
+1);
4249 } else if (cmp
[0] == '>') {
4250 if (cmp
[1] == '=') {
4251 discrim
->max_registered
= now
- ParseInterval(cmp
+2);
4253 discrim
->max_registered
= now
- ParseInterval(cmp
+1) - 1;
4256 reply("MSG_INVALID_CRITERIA", cmp
);
4258 } else if (!irccasecmp(argv
[i
], "seen")) {
4259 discrim
->lastseen
= now
- ParseInterval(argv
[++i
]);
4260 } else if (!nickserv_conf
.disable_nicks
&& !irccasecmp(argv
[i
], "nickmask")) {
4261 discrim
->nickmask
= argv
[++i
];
4262 } else if (!irccasecmp(argv
[i
], "hostmask")) {
4264 if (!irccasecmp(argv
[i
], "exact")) {
4265 if (i
== argc
- 1) {
4266 reply("MSG_MISSING_PARAMS", argv
[i
]);
4269 discrim
->hostmask_type
= EXACT
;
4270 } else if (!irccasecmp(argv
[i
], "subset")) {
4271 if (i
== argc
- 1) {
4272 reply("MSG_MISSING_PARAMS", argv
[i
]);
4275 discrim
->hostmask_type
= SUBSET
;
4276 } else if (!irccasecmp(argv
[i
], "superset")) {
4277 if (i
== argc
- 1) {
4278 reply("MSG_MISSING_PARAMS", argv
[i
]);
4281 discrim
->hostmask_type
= SUPERSET
;
4282 } else if (!irccasecmp(argv
[i
], "lastquit") || !irccasecmp(argv
[i
], "lastauth")) {
4283 if (i
== argc
- 1) {
4284 reply("MSG_MISSING_PARAMS", argv
[i
]);
4287 discrim
->hostmask_type
= LASTQUIT
;
4290 discrim
->hostmask_type
= SUPERSET
;
4292 discrim
->hostmask
= argv
[++i
];
4293 } else if (!irccasecmp(argv
[i
], "handlemask") || !irccasecmp(argv
[i
], "accountmask") || !irccasecmp(argv
[i
], "account")) {
4294 if (!irccasecmp(argv
[++i
], "*")) {
4295 discrim
->handlemask
= 0;
4297 discrim
->handlemask
= argv
[i
];
4299 } else if (!irccasecmp(argv
[i
], "email")) {
4300 if (user
->handle_info
->opserv_level
< nickserv_conf
.email_search_level
) {
4301 reply("MSG_NO_SEARCH_ACCESS", "email");
4303 } else if (!irccasecmp(argv
[++i
], "*")) {
4304 discrim
->emailmask
= 0;
4306 discrim
->emailmask
= argv
[i
];
4308 } else if (!irccasecmp(argv
[i
], "access")) {
4309 const char *cmp
= argv
[++i
];
4310 if (cmp
[0] == '<') {
4311 if (discrim
->min_level
== 0) discrim
->min_level
= 1;
4312 if (cmp
[1] == '=') {
4313 discrim
->max_level
= strtoul(cmp
+2, NULL
, 0);
4315 discrim
->max_level
= strtoul(cmp
+1, NULL
, 0) - 1;
4317 } else if (cmp
[0] == '=') {
4318 discrim
->min_level
= discrim
->max_level
= strtoul(cmp
+1, NULL
, 0);
4319 } else if (cmp
[0] == '>') {
4320 if (cmp
[1] == '=') {
4321 discrim
->min_level
= strtoul(cmp
+2, NULL
, 0);
4323 discrim
->min_level
= strtoul(cmp
+1, NULL
, 0) + 1;
4326 reply("MSG_INVALID_CRITERIA", cmp
);
4328 } else if (!irccasecmp(argv
[i
], "karma")) {
4329 const char *cmp
= argv
[++i
];
4330 if (cmp
[0] == '<') {
4331 if (cmp
[1] == '=') {
4332 discrim
->max_karma
= strtoul(cmp
+2, NULL
, 0);
4334 discrim
->max_karma
= strtoul(cmp
+1, NULL
, 0) - 1;
4336 } else if (cmp
[0] == '=') {
4337 discrim
->min_karma
= discrim
->max_karma
= strtoul(cmp
+1, NULL
, 0);
4338 } else if (cmp
[0] == '>') {
4339 if (cmp
[1] == '=') {
4340 discrim
->min_karma
= strtoul(cmp
+2, NULL
, 0);
4342 discrim
->min_karma
= strtoul(cmp
+1, NULL
, 0) + 1;
4345 send_message(user
, nickserv
, "MSG_INVALID_CRITERIA", cmp
);
4348 } else if (nickserv_conf
.ldap_enable
&& !irccasecmp(argv
[i
], "inldap")) {
4350 if(true_string(argv
[i
])) {
4351 discrim
->inldap
= 1;
4353 else if (false_string(argv
[i
])) {
4354 discrim
->inldap
= 0;
4357 reply("MSG_INVALID_BINARY", argv
[i
]);
4361 reply("MSG_INVALID_CRITERIA", argv
[i
]);
4372 nickserv_discrim_match(struct nickserv_discrim
*discrim
, struct handle_info
*hi
)
4374 if (((discrim
->flags_on
& hi
->flags
) != discrim
->flags_on
)
4375 || (discrim
->flags_off
& hi
->flags
)
4376 || (discrim
->min_registered
> hi
->registered
)
4377 || (discrim
->max_registered
< hi
->registered
)
4378 || (discrim
->lastseen
< (hi
->users
?now
:hi
->lastseen
))
4379 || (discrim
->handlemask
&& !match_ircglob(hi
->handle
, discrim
->handlemask
))
4380 || (discrim
->emailmask
&& (!hi
->email_addr
|| !match_ircglob(hi
->email_addr
, discrim
->emailmask
)))
4381 || (discrim
->min_level
> hi
->opserv_level
)
4382 || (discrim
->max_level
< hi
->opserv_level
)
4383 || (discrim
->min_karma
> hi
->karma
)
4384 || (discrim
->max_karma
< hi
->karma
)
4388 if (discrim
->hostmask
) {
4390 for (i
=0; i
<hi
->masks
->used
; i
++) {
4391 const char *mask
= hi
->masks
->list
[i
];
4392 if ((discrim
->hostmask_type
== SUBSET
)
4393 && (match_ircglobs(discrim
->hostmask
, mask
))) break;
4394 else if ((discrim
->hostmask_type
== EXACT
)
4395 && !irccasecmp(discrim
->hostmask
, mask
)) break;
4396 else if ((discrim
->hostmask_type
== SUPERSET
)
4397 && (match_ircglobs(mask
, discrim
->hostmask
))) break;
4398 else if ((discrim
->hostmask_type
== LASTQUIT
)
4399 && (match_ircglobs(discrim
->hostmask
, hi
->last_quit_host
))) break;
4401 if (i
==hi
->masks
->used
) return 0;
4403 if (discrim
->nickmask
) {
4404 struct nick_info
*nick
= hi
->nicks
;
4406 if (match_ircglob(nick
->nick
, discrim
->nickmask
)) break;
4409 if (!nick
) return 0;
4412 if(nickserv_conf
.ldap_enable
&& discrim
->inldap
!= 2) {
4414 rc
= ldap_get_user_info(hi
->handle
, NULL
);
4415 if(discrim
->inldap
== 1 && rc
!= LDAP_SUCCESS
)
4417 if(discrim
->inldap
== 0 && rc
== LDAP_SUCCESS
)
4426 nickserv_discrim_search(struct nickserv_discrim
*discrim
, discrim_search_func dsf
, struct userNode
*source
)
4428 dict_iterator_t it
, next
;
4429 unsigned int matched
;
4431 for (it
= dict_first(nickserv_handle_dict
), matched
= 0;
4432 it
&& (matched
< discrim
->limit
);
4434 next
= iter_next(it
);
4435 if (nickserv_discrim_match(discrim
, iter_data(it
))) {
4436 dsf(source
, iter_data(it
));
4444 search_print_func(struct userNode
*source
, struct handle_info
*match
)
4446 send_message(source
, nickserv
, "NSMSG_SEARCH_MATCH", match
->handle
);
4450 search_count_func(UNUSED_ARG(struct userNode
*source
), UNUSED_ARG(struct handle_info
*match
))
4455 search_unregister_func (struct userNode
*source
, struct handle_info
*match
)
4457 if (oper_has_access(source
, nickserv
, match
->opserv_level
, 0))
4458 nickserv_unregister_handle(match
, source
, nickserv
); // XXX nickserv hard coded
4463 search_add2ldap_func (struct userNode
*source
, struct handle_info
*match
)
4466 if(match
->email_addr
&& match
->passwd
&& match
->handle
) {
4467 rc
= ldap_do_add(match
->handle
, match
->passwd
, match
->email_addr
);
4468 if(rc
!= LDAP_SUCCESS
) {
4469 send_message(source
, nickserv
, "NSMSG_LDAP_FAIL_ADD", match
->handle
, ldap_err2string(rc
));
4476 nickserv_sort_accounts_by_access(const void *a
, const void *b
)
4478 const struct handle_info
*hi_a
= *(const struct handle_info
**)a
;
4479 const struct handle_info
*hi_b
= *(const struct handle_info
**)b
;
4480 if (hi_a
->opserv_level
!= hi_b
->opserv_level
)
4481 return hi_b
->opserv_level
- hi_a
->opserv_level
;
4482 return irccasecmp(hi_a
->handle
, hi_b
->handle
);
4486 nickserv_show_oper_accounts(struct userNode
*user
, struct svccmd
*cmd
)
4488 struct handle_info_list hil
;
4489 struct helpfile_table tbl
;
4494 memset(&hil
, 0, sizeof(hil
));
4495 for (it
= dict_first(nickserv_handle_dict
); it
; it
= iter_next(it
)) {
4496 struct handle_info
*hi
= iter_data(it
);
4497 if (hi
->opserv_level
)
4498 handle_info_list_append(&hil
, hi
);
4500 qsort(hil
.list
, hil
.used
, sizeof(hil
.list
[0]), nickserv_sort_accounts_by_access
);
4501 tbl
.length
= hil
.used
+ 1;
4503 tbl
.flags
= TABLE_NO_FREE
| TABLE_REPEAT_ROWS
| TABLE_REPEAT_HEADERS
;
4504 tbl
.contents
= malloc(tbl
.length
* sizeof(tbl
.contents
[0]));
4505 tbl
.contents
[0] = ary
= malloc(tbl
.width
* sizeof(ary
[0]));
4508 for (ii
= 0; ii
< hil
.used
; ) {
4509 ary
= malloc(tbl
.width
* sizeof(ary
[0]));
4510 ary
[0] = hil
.list
[ii
]->handle
;
4511 ary
[1] = strtab(hil
.list
[ii
]->opserv_level
);
4512 tbl
.contents
[++ii
] = ary
;
4514 table_send(cmd
->parent
->bot
, user
->nick
, 0, NULL
, tbl
);
4515 /*reply("MSG_MATCH_COUNT", hil.used); */
4516 for (ii
= 0; ii
< hil
.used
; ii
++)
4517 free(tbl
.contents
[ii
]);
4522 static NICKSERV_FUNC(cmd_search
)
4524 struct nickserv_discrim
*discrim
;
4525 discrim_search_func action
;
4526 struct svccmd
*subcmd
;
4527 unsigned int matches
;
4530 NICKSERV_MIN_PARMS(3);
4531 sprintf(buf
, "search %s", argv
[1]);
4532 subcmd
= dict_find(nickserv_service
->commands
, buf
, NULL
);
4533 if (!irccasecmp(argv
[1], "print"))
4534 action
= search_print_func
;
4535 else if (!irccasecmp(argv
[1], "count"))
4536 action
= search_count_func
;
4537 else if (!irccasecmp(argv
[1], "unregister"))
4538 action
= search_unregister_func
;
4540 else if (nickserv_conf
.ldap_enable
&& !irccasecmp(argv
[1], "add2ldap"))
4541 action
= search_add2ldap_func
;
4544 reply("NSMSG_INVALID_ACTION", argv
[1]);
4548 if (subcmd
&& !svccmd_can_invoke(user
, nickserv
, subcmd
, NULL
, SVCCMD_NOISY
))
4551 discrim
= nickserv_discrim_create(cmd
, user
, argc
-2, argv
+2);
4555 if (action
== search_print_func
)
4556 reply("NSMSG_ACCOUNT_SEARCH_RESULTS");
4557 else if (action
== search_count_func
)
4558 discrim
->limit
= INT_MAX
;
4560 matches
= nickserv_discrim_search(discrim
, action
, user
);
4563 reply("MSG_MATCH_COUNT", matches
);
4565 reply("MSG_NO_MATCHES");
4571 static MODCMD_FUNC(cmd_checkpass
)
4573 struct handle_info
*hi
;
4575 NICKSERV_MIN_PARMS(3);
4576 if (!(hi
= get_handle_info(argv
[1]))) {
4577 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
4580 if (checkpass(argv
[2], hi
->passwd
))
4581 reply("CHECKPASS_YES");
4583 reply("CHECKPASS_NO");
4588 static MODCMD_FUNC(cmd_checkemail
)
4590 struct handle_info
*hi
;
4592 NICKSERV_MIN_PARMS(3);
4593 if (!(hi
= modcmd_get_handle_info(user
, argv
[1]))) {
4596 if (!hi
->email_addr
)
4597 reply("CHECKEMAIL_NOT_SET");
4598 else if (!irccasecmp(argv
[2], hi
->email_addr
))
4599 reply("CHECKEMAIL_YES");
4601 reply("CHECKEMAIL_NO");
4606 nickserv_db_read_handle(char *handle
, dict_t obj
)
4609 struct string_list
*masks
, *sslfps
, *slist
, *ignores
;
4610 struct handle_info
*hi
;
4611 struct userNode
*authed_users
;
4612 struct userData
*channel_list
;
4613 unsigned long int id
;
4616 char *setter
, *note
;
4619 str
= database_get_data(obj
, KEY_ID
, RECDB_QSTRING
);
4620 id
= str
? strtoul(str
, NULL
, 0) : 0;
4621 str
= database_get_data(obj
, KEY_PASSWD
, RECDB_QSTRING
);
4623 log_module(NS_LOG
, LOG_WARNING
, "did not find a password for %s -- skipping user.", handle
);
4626 if ((hi
= get_handle_info(handle
))) {
4627 authed_users
= hi
->users
;
4628 channel_list
= hi
->channels
;
4630 hi
->channels
= NULL
;
4631 dict_remove(nickserv_handle_dict
, hi
->handle
);
4633 authed_users
= NULL
;
4634 channel_list
= NULL
;
4636 if(nickserv_conf
.force_handles_lowercase
)
4637 irc_strtolower(handle
);
4638 hi
= register_handle(handle
, str
, id
);
4640 hi
->users
= authed_users
;
4641 while (authed_users
) {
4642 authed_users
->handle_info
= hi
;
4643 authed_users
= authed_users
->next_authed
;
4646 hi
->channels
= channel_list
;
4647 masks
= database_get_data(obj
, KEY_MASKS
, RECDB_STRING_LIST
);
4648 hi
->masks
= masks
? string_list_copy(masks
) : alloc_string_list(1);
4649 sslfps
= database_get_data(obj
, KEY_SSLFPS
, RECDB_STRING_LIST
);
4650 hi
->sslfps
= sslfps
? string_list_copy(sslfps
) : alloc_string_list(1);
4651 ignores
= database_get_data(obj
, KEY_IGNORES
, RECDB_STRING_LIST
);
4652 hi
->ignores
= ignores
? string_list_copy(ignores
) : alloc_string_list(1);
4653 str
= database_get_data(obj
, KEY_MAXLOGINS
, RECDB_QSTRING
);
4654 hi
->maxlogins
= str
? strtoul(str
, NULL
, 0) : 0;
4655 str
= database_get_data(obj
, KEY_LANGUAGE
, RECDB_QSTRING
);
4656 hi
->language
= language_find(str
? str
: "C");
4657 str
= database_get_data(obj
, KEY_OPSERV_LEVEL
, RECDB_QSTRING
);
4658 hi
->opserv_level
= str
? strtoul(str
, NULL
, 0) : 0;
4659 str
= database_get_data(obj
, KEY_INFO
, RECDB_QSTRING
);
4661 hi
->infoline
= strdup(str
);
4662 str
= database_get_data(obj
, KEY_REGISTER_ON
, RECDB_QSTRING
);
4663 hi
->registered
= str
? (time_t)strtoul(str
, NULL
, 0) : now
;
4664 str
= database_get_data(obj
, KEY_LAST_SEEN
, RECDB_QSTRING
);
4665 hi
->lastseen
= str
? (time_t)strtoul(str
, NULL
, 0) : hi
->registered
;
4666 str
= database_get_data(obj
, KEY_KARMA
, RECDB_QSTRING
);
4667 hi
->karma
= str
? strtoul(str
, NULL
, 0) : 0;
4668 /* We want to read the nicks even if disable_nicks is set. This is so
4669 * that we don't lose the nick data entirely. */
4670 slist
= database_get_data(obj
, KEY_NICKS
, RECDB_STRING_LIST
);
4672 for (ii
=0; ii
<slist
->used
; ii
++)
4673 register_nick(slist
->list
[ii
], hi
);
4675 str
= database_get_data(obj
, KEY_FLAGS
, RECDB_QSTRING
);
4677 for (ii
=0; str
[ii
]; ii
++)
4678 hi
->flags
|= 1 << (handle_inverse_flags
[(unsigned char)str
[ii
]] - 1);
4680 str
= database_get_data(obj
, KEY_USERLIST_STYLE
, RECDB_QSTRING
);
4681 hi
->userlist_style
= str
? str
[0] : HI_DEFAULT_STYLE
;
4682 str
= database_get_data(obj
, KEY_ANNOUNCEMENTS
, RECDB_QSTRING
);
4683 hi
->announcements
= str
? str
[0] : '?';
4684 str
= database_get_data(obj
, KEY_SCREEN_WIDTH
, RECDB_QSTRING
);
4685 hi
->screen_width
= str
? strtoul(str
, NULL
, 0) : 0;
4686 str
= database_get_data(obj
, KEY_TABLE_WIDTH
, RECDB_QSTRING
);
4687 hi
->table_width
= str
? strtoul(str
, NULL
, 0) : 0;
4688 str
= database_get_data(obj
, KEY_LAST_QUIT_HOST
, RECDB_QSTRING
);
4690 str
= database_get_data(obj
, KEY_LAST_AUTHED_HOST
, RECDB_QSTRING
);
4692 safestrncpy(hi
->last_quit_host
, str
, sizeof(hi
->last_quit_host
));
4693 str
= database_get_data(obj
, KEY_EMAIL_ADDR
, RECDB_QSTRING
);
4695 nickserv_set_email_addr(hi
, str
);
4696 str
= database_get_data(obj
, KEY_EPITHET
, RECDB_QSTRING
);
4698 hi
->epithet
= strdup(str
);
4699 subdb
= database_get_data(obj
, KEY_NOTE_NOTE
, RECDB_OBJECT
);
4701 setter
= database_get_data(subdb
, KEY_NOTE_SETTER
, RECDB_QSTRING
);
4702 str
= database_get_data(subdb
, KEY_NOTE_DATE
, RECDB_QSTRING
);
4703 date
= str
? (time_t)strtoul(str
, NULL
, 0) : now
;
4704 note
= database_get_data(subdb
, KEY_NOTE_NOTE
, RECDB_QSTRING
);
4705 if (setter
&& date
&& note
)
4707 if (!(hi
->note
= nickserv_add_note(setter
, date
, note
)))
4712 str
= database_get_data(obj
, KEY_FAKEHOST
, RECDB_QSTRING
);
4714 hi
->fakehost
= strdup(str
);
4716 subdb
= database_get_data(obj
, KEY_COOKIE
, RECDB_OBJECT
);
4718 const char *data
, *type
, *expires
, *cookie_str
;
4719 struct handle_cookie
*cookie
;
4721 cookie
= calloc(1, sizeof(*cookie
));
4722 type
= database_get_data(subdb
, KEY_COOKIE_TYPE
, RECDB_QSTRING
);
4723 data
= database_get_data(subdb
, KEY_COOKIE_DATA
, RECDB_QSTRING
);
4724 expires
= database_get_data(subdb
, KEY_COOKIE_EXPIRES
, RECDB_QSTRING
);
4725 cookie_str
= database_get_data(subdb
, KEY_COOKIE
, RECDB_QSTRING
);
4726 if (!type
|| !expires
|| !cookie_str
) {
4727 log_module(NS_LOG
, LOG_ERROR
, "Missing field(s) from cookie for account %s; dropping cookie.", hi
->handle
);
4730 if (!irccasecmp(type
, KEY_ACTIVATION
))
4731 cookie
->type
= ACTIVATION
;
4732 else if (!irccasecmp(type
, KEY_PASSWORD_CHANGE
))
4733 cookie
->type
= PASSWORD_CHANGE
;
4734 else if (!irccasecmp(type
, KEY_EMAIL_CHANGE
))
4735 cookie
->type
= EMAIL_CHANGE
;
4736 else if (!irccasecmp(type
, KEY_ALLOWAUTH
))
4737 cookie
->type
= ALLOWAUTH
;
4739 log_module(NS_LOG
, LOG_ERROR
, "Invalid cookie type %s for account %s; dropping cookie.", type
, handle
);
4742 cookie
->expires
= strtoul(expires
, NULL
, 0);
4743 if (cookie
->expires
< now
)
4746 cookie
->data
= strdup(data
);
4747 safestrncpy(cookie
->cookie
, cookie_str
, sizeof(cookie
->cookie
));
4751 nickserv_bake_cookie(cookie
);
4753 nickserv_free_cookie(cookie
);
4758 nickserv_saxdb_read(dict_t db
) {
4760 struct record_data
*rd
;
4763 for (it
=dict_first(db
); it
; it
=iter_next(it
)) {
4765 handle
= strdup(iter_key(it
));
4766 nickserv_db_read_handle(handle
, rd
->d
.object
);
4772 static NICKSERV_FUNC(cmd_mergedb
)
4774 struct timeval start
, stop
;
4777 NICKSERV_MIN_PARMS(2);
4778 gettimeofday(&start
, NULL
);
4779 if (!(db
= parse_database(argv
[1]))) {
4780 reply("NSMSG_DB_UNREADABLE", argv
[1]);
4783 nickserv_saxdb_read(db
);
4785 gettimeofday(&stop
, NULL
);
4786 stop
.tv_sec
-= start
.tv_sec
;
4787 stop
.tv_usec
-= start
.tv_usec
;
4788 if (stop
.tv_usec
< 0) {
4790 stop
.tv_usec
+= 1000000;
4792 reply("NSMSG_DB_MERGED", argv
[1], stop
.tv_sec
, stop
.tv_usec
/1000);
4797 expire_handles(UNUSED_ARG(void *data
))
4799 dict_iterator_t it
, next
;
4801 struct handle_info
*hi
;
4803 for (it
=dict_first(nickserv_handle_dict
); it
; it
=next
) {
4804 next
= iter_next(it
);
4806 if ((hi
->opserv_level
> 0)
4808 || HANDLE_FLAGGED(hi
, FROZEN
)
4809 || HANDLE_FLAGGED(hi
, NODELETE
)) {
4812 expiry
= hi
->channels
? nickserv_conf
.handle_expire_delay
: nickserv_conf
.nochan_handle_expire_delay
;
4813 if ((now
- hi
->lastseen
) > expiry
) {
4814 log_module(NS_LOG
, LOG_INFO
, "Expiring account %s for inactivity.", hi
->handle
);
4815 nickserv_unregister_handle(hi
, NULL
, NULL
);
4819 if (nickserv_conf
.handle_expire_frequency
)
4820 timeq_add(now
+ nickserv_conf
.handle_expire_frequency
, expire_handles
, NULL
);
4824 nickserv_load_dict(const char *fname
)
4828 if (!(file
= fopen(fname
, "r"))) {
4829 log_module(NS_LOG
, LOG_ERROR
, "Unable to open dictionary file %s: %s", fname
, strerror(errno
));
4832 while (fgets(line
, sizeof(line
), file
)) {
4835 if (line
[strlen(line
)-1] == '\n')
4836 line
[strlen(line
)-1] = 0;
4837 dict_insert(nickserv_conf
.weak_password_dict
, strdup(line
), NULL
);
4840 log_module(NS_LOG
, LOG_INFO
, "Loaded %d words into weak password dictionary.", dict_size(nickserv_conf
.weak_password_dict
));
4843 static enum reclaim_action
4844 reclaim_action_from_string(const char *str
) {
4846 return RECLAIM_NONE
;
4847 else if (!irccasecmp(str
, "warn"))
4848 return RECLAIM_WARN
;
4849 else if (!irccasecmp(str
, "svsnick"))
4850 return RECLAIM_SVSNICK
;
4851 else if (!irccasecmp(str
, "kill"))
4852 return RECLAIM_KILL
;
4854 return RECLAIM_NONE
;
4858 nickserv_conf_read(void)
4860 dict_t conf_node
, child
;
4863 struct string_list
*strlist
;
4865 if (!(conf_node
= conf_get_data(NICKSERV_CONF_NAME
, RECDB_OBJECT
))) {
4866 log_module(NS_LOG
, LOG_ERROR
, "config node `%s' is missing or has wrong type.", NICKSERV_CONF_NAME
);
4869 str
= database_get_data(conf_node
, KEY_VALID_HANDLE_REGEX
, RECDB_QSTRING
);
4871 str
= database_get_data(conf_node
, KEY_VALID_ACCOUNT_REGEX
, RECDB_QSTRING
);
4872 if (nickserv_conf
.valid_handle_regex_set
)
4873 regfree(&nickserv_conf
.valid_handle_regex
);
4875 int err
= regcomp(&nickserv_conf
.valid_handle_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
4876 nickserv_conf
.valid_handle_regex_set
= !err
;
4877 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_account_regex (error %d)", err
);
4879 nickserv_conf
.valid_handle_regex_set
= 0;
4881 str
= database_get_data(conf_node
, KEY_VALID_NICK_REGEX
, RECDB_QSTRING
);
4882 if (nickserv_conf
.valid_nick_regex_set
)
4883 regfree(&nickserv_conf
.valid_nick_regex
);
4885 int err
= regcomp(&nickserv_conf
.valid_nick_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
4886 nickserv_conf
.valid_nick_regex_set
= !err
;
4887 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_nick_regex (error %d)", err
);
4889 nickserv_conf
.valid_nick_regex_set
= 0;
4891 str
= database_get_data(conf_node
, KEY_VALID_FAKEHOST_REGEX
, RECDB_QSTRING
);
4892 if (nickserv_conf
.valid_fakehost_regex_set
)
4893 regfree(&nickserv_conf
.valid_fakehost_regex
);
4895 int err
= regcomp(&nickserv_conf
.valid_fakehost_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
4896 nickserv_conf
.valid_fakehost_regex_set
= !err
;
4897 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_fakehost_regex (error %d)", err
);
4899 nickserv_conf
.valid_fakehost_regex_set
= 0;
4901 str
= database_get_data(conf_node
, KEY_NICKS_PER_HANDLE
, RECDB_QSTRING
);
4903 str
= database_get_data(conf_node
, KEY_NICKS_PER_ACCOUNT
, RECDB_QSTRING
);
4904 nickserv_conf
.nicks_per_handle
= str
? strtoul(str
, NULL
, 0) : 4;
4905 str
= database_get_data(conf_node
, KEY_DISABLE_NICKS
, RECDB_QSTRING
);
4906 nickserv_conf
.disable_nicks
= str
? strtoul(str
, NULL
, 0) : 0;
4907 str
= database_get_data(conf_node
, KEY_DEFAULT_HOSTMASK
, RECDB_QSTRING
);
4908 nickserv_conf
.default_hostmask
= str
? !disabled_string(str
) : 0;
4909 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_LENGTH
, RECDB_QSTRING
);
4910 nickserv_conf
.password_min_length
= str
? strtoul(str
, NULL
, 0) : 0;
4911 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_DIGITS
, RECDB_QSTRING
);
4912 nickserv_conf
.password_min_digits
= str
? strtoul(str
, NULL
, 0) : 0;
4913 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_UPPER
, RECDB_QSTRING
);
4914 nickserv_conf
.password_min_upper
= str
? strtoul(str
, NULL
, 0) : 0;
4915 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_LOWER
, RECDB_QSTRING
);
4916 nickserv_conf
.password_min_lower
= str
? strtoul(str
, NULL
, 0) : 0;
4917 str
= database_get_data(conf_node
, KEY_DB_BACKUP_FREQ
, RECDB_QSTRING
);
4918 nickserv_conf
.db_backup_frequency
= str
? ParseInterval(str
) : 7200;
4919 str
= database_get_data(conf_node
, KEY_MODOPER_LEVEL
, RECDB_QSTRING
);
4920 nickserv_conf
.modoper_level
= str
? strtoul(str
, NULL
, 0) : 900;
4921 str
= database_get_data(conf_node
, KEY_SET_EPITHET_LEVEL
, RECDB_QSTRING
);
4922 nickserv_conf
.set_epithet_level
= str
? strtoul(str
, NULL
, 0) : 1;
4923 str
= database_get_data(conf_node
, KEY_SET_TITLE_LEVEL
, RECDB_QSTRING
);
4924 nickserv_conf
.set_title_level
= str
? strtoul(str
, NULL
, 0) : 900;
4925 str
= database_get_data(conf_node
, KEY_SET_FAKEHOST_LEVEL
, RECDB_QSTRING
);
4926 nickserv_conf
.set_fakehost_level
= str
? strtoul(str
, NULL
, 0) : 1000;
4927 str
= database_get_data(conf_node
, KEY_HANDLE_EXPIRE_FREQ
, RECDB_QSTRING
);
4929 str
= database_get_data(conf_node
, KEY_ACCOUNT_EXPIRE_FREQ
, RECDB_QSTRING
);
4930 nickserv_conf
.handle_expire_frequency
= str
? ParseInterval(str
) : 86400;
4931 str
= database_get_data(conf_node
, KEY_HANDLE_EXPIRE_DELAY
, RECDB_QSTRING
);
4933 str
= database_get_data(conf_node
, KEY_ACCOUNT_EXPIRE_DELAY
, RECDB_QSTRING
);
4934 nickserv_conf
.handle_expire_delay
= str
? ParseInterval(str
) : 86400*30;
4935 str
= database_get_data(conf_node
, KEY_NOCHAN_HANDLE_EXPIRE_DELAY
, RECDB_QSTRING
);
4937 str
= database_get_data(conf_node
, KEY_NOCHAN_ACCOUNT_EXPIRE_DELAY
, RECDB_QSTRING
);
4938 nickserv_conf
.nochan_handle_expire_delay
= str
? ParseInterval(str
) : 86400*15;
4939 str
= database_get_data(conf_node
, "warn_clone_auth", RECDB_QSTRING
);
4940 nickserv_conf
.warn_clone_auth
= str
? !disabled_string(str
) : 1;
4941 str
= database_get_data(conf_node
, "default_maxlogins", RECDB_QSTRING
);
4942 nickserv_conf
.default_maxlogins
= str
? strtoul(str
, NULL
, 0) : 2;
4943 str
= database_get_data(conf_node
, "hard_maxlogins", RECDB_QSTRING
);
4944 str
= database_get_data(conf_node
, KEY_OUNREGISTER_INACTIVE
, RECDB_QSTRING
);
4945 nickserv_conf
.ounregister_inactive
= str
? ParseInterval(str
) : 86400*28;
4946 str
= database_get_data(conf_node
, KEY_OUNREGISTER_FLAGS
, RECDB_QSTRING
);
4949 nickserv_conf
.ounregister_flags
= 0;
4951 unsigned int pos
= handle_inverse_flags
[(unsigned char)*str
];
4954 nickserv_conf
.ounregister_flags
|= 1 << (pos
- 1);
4956 nickserv_conf
.hard_maxlogins
= str
? strtoul(str
, NULL
, 0) : 10;
4957 if (!nickserv_conf
.disable_nicks
) {
4958 str
= database_get_data(conf_node
, "reclaim_action", RECDB_QSTRING
);
4959 nickserv_conf
.reclaim_action
= str
? reclaim_action_from_string(str
) : RECLAIM_NONE
;
4960 str
= database_get_data(conf_node
, "warn_nick_owned", RECDB_QSTRING
);
4961 nickserv_conf
.warn_nick_owned
= str
? enabled_string(str
) : 0;
4962 str
= database_get_data(conf_node
, "auto_reclaim_action", RECDB_QSTRING
);
4963 nickserv_conf
.auto_reclaim_action
= str
? reclaim_action_from_string(str
) : RECLAIM_NONE
;
4964 str
= database_get_data(conf_node
, "auto_reclaim_delay", RECDB_QSTRING
);
4965 nickserv_conf
.auto_reclaim_delay
= str
? ParseInterval(str
) : 0;
4967 child
= database_get_data(conf_node
, KEY_FLAG_LEVELS
, RECDB_OBJECT
);
4968 for (it
=dict_first(child
); it
; it
=iter_next(it
)) {
4969 const char *key
= iter_key(it
), *value
;
4973 if (!strncasecmp(key
, "uc_", 3))
4974 flag
= toupper(key
[3]);
4975 else if (!strncasecmp(key
, "lc_", 3))
4976 flag
= tolower(key
[3]);
4980 if ((pos
= handle_inverse_flags
[flag
])) {
4981 value
= GET_RECORD_QSTRING((struct record_data
*)iter_data(it
));
4982 flag_access_levels
[pos
- 1] = strtoul(value
, NULL
, 0);
4985 if (nickserv_conf
.weak_password_dict
)
4986 dict_delete(nickserv_conf
.weak_password_dict
);
4987 nickserv_conf
.weak_password_dict
= dict_new();
4988 dict_set_free_keys(nickserv_conf
.weak_password_dict
, free
);
4989 dict_insert(nickserv_conf
.weak_password_dict
, strdup("password"), NULL
);
4990 dict_insert(nickserv_conf
.weak_password_dict
, strdup("<password>"), NULL
);
4991 str
= database_get_data(conf_node
, KEY_DICT_FILE
, RECDB_QSTRING
);
4993 nickserv_load_dict(str
);
4994 str
= database_get_data(conf_node
, KEY_NICK
, RECDB_QSTRING
);
4995 if (nickserv
&& str
)
4996 NickChange(nickserv
, str
, 0);
4997 str
= database_get_data(conf_node
, KEY_AUTOGAG_ENABLED
, RECDB_QSTRING
);
4998 nickserv_conf
.autogag_enabled
= str
? strtoul(str
, NULL
, 0) : 1;
4999 str
= database_get_data(conf_node
, KEY_AUTOGAG_DURATION
, RECDB_QSTRING
);
5000 nickserv_conf
.autogag_duration
= str
? ParseInterval(str
) : 1800;
5001 str
= database_get_data(conf_node
, KEY_EMAIL_VISIBLE_LEVEL
, RECDB_QSTRING
);
5002 nickserv_conf
.email_visible_level
= str
? strtoul(str
, NULL
, 0) : 800;
5003 str
= database_get_data(conf_node
, KEY_EMAIL_ENABLED
, RECDB_QSTRING
);
5004 nickserv_conf
.email_enabled
= str
? enabled_string(str
) : 0;
5005 str
= database_get_data(conf_node
, KEY_SYNC_LOG
, RECDB_QSTRING
);
5006 nickserv_conf
.sync_log
= str
? enabled_string(str
) : 0;
5007 str
= database_get_data(conf_node
, KEY_COOKIE_TIMEOUT
, RECDB_QSTRING
);
5008 nickserv_conf
.cookie_timeout
= str
? ParseInterval(str
) : 24*3600;
5009 str
= database_get_data(conf_node
, KEY_EMAIL_REQUIRED
, RECDB_QSTRING
);
5010 nickserv_conf
.email_required
= (nickserv_conf
.email_enabled
&& str
) ? enabled_string(str
) : 0;
5011 str
= database_get_data(conf_node
, KEY_ACCOUNTS_PER_EMAIL
, RECDB_QSTRING
);
5012 nickserv_conf
.handles_per_email
= str
? strtoul(str
, NULL
, 0) : 1;
5013 str
= database_get_data(conf_node
, KEY_EMAIL_SEARCH_LEVEL
, RECDB_QSTRING
);
5014 nickserv_conf
.email_search_level
= str
? strtoul(str
, NULL
, 0) : 600;
5015 str
= database_get_data(conf_node
, KEY_TITLEHOST_SUFFIX
, RECDB_QSTRING
);
5016 nickserv_conf
.titlehost_suffix
= str
? str
: "example.net";
5018 free_string_list(nickserv_conf
.denied_fakehost_words
);
5019 strlist
= database_get_data(conf_node
, KEY_DENIED_FAKEHOST_WORDS
, RECDB_STRING_LIST
);
5021 strlist
= string_list_copy(strlist
);
5023 strlist
= alloc_string_list(4);
5024 string_list_append(strlist
, strdup("sex"));
5025 string_list_append(strlist
, strdup("fuck"));
5027 nickserv_conf
.denied_fakehost_words
= strlist
;
5029 str
= database_get_data(conf_node
, KEY_DEFAULT_STYLE
, RECDB_QSTRING
);
5030 nickserv_conf
.default_style
= str
? str
[0] : HI_DEFAULT_STYLE
;
5032 str
= database_get_data(conf_node
, KEY_AUTO_OPER
, RECDB_QSTRING
);
5033 nickserv_conf
.auto_oper
= str
? str
: "";
5035 str
= database_get_data(conf_node
, KEY_AUTO_ADMIN
, RECDB_QSTRING
);
5036 nickserv_conf
.auto_admin
= str
? str
: "";
5038 str
= database_get_data(conf_node
, KEY_AUTO_OPER_PRIVS
, RECDB_QSTRING
);
5039 nickserv_conf
.auto_oper_privs
= str
? str
: "";
5041 str
= database_get_data(conf_node
, KEY_AUTO_ADMIN_PRIVS
, RECDB_QSTRING
);
5042 nickserv_conf
.auto_admin_privs
= str
? str
: "";
5044 str
= conf_get_data("server/network", RECDB_QSTRING
);
5045 nickserv_conf
.network_name
= str
? str
: "some IRC network";
5046 if (!nickserv_conf
.auth_policer_params
) {
5047 nickserv_conf
.auth_policer_params
= policer_params_new();
5048 policer_params_set(nickserv_conf
.auth_policer_params
, "size", "5");
5049 policer_params_set(nickserv_conf
.auth_policer_params
, "drain-rate", "0.05");
5051 child
= database_get_data(conf_node
, KEY_AUTH_POLICER
, RECDB_OBJECT
);
5052 for (it
=dict_first(child
); it
; it
=iter_next(it
))
5053 set_policer_param(iter_key(it
), iter_data(it
), nickserv_conf
.auth_policer_params
);
5055 str
= database_get_data(conf_node
, KEY_LDAP_ENABLE
, RECDB_QSTRING
);
5056 nickserv_conf
.ldap_enable
= str
? strtoul(str
, NULL
, 0) : 0;
5058 str
= database_get_data(conf_node
, KEY_FORCE_HANDLES_LOWERCASE
, RECDB_QSTRING
);
5059 nickserv_conf
.force_handles_lowercase
= str
? strtol(str
, NULL
, 0) : 0;
5062 if(nickserv_conf
.ldap_enable
> 0) {
5063 /* ldap is enabled but not compiled in - error out */
5064 log_module(MAIN_LOG
, LOG_ERROR
, "ldap is enabled in config, but not compiled in!");
5065 nickserv_conf
.ldap_enable
= 0;
5071 str
= database_get_data(conf_node
, KEY_LDAP_URI
, RECDB_QSTRING
);
5072 nickserv_conf
.ldap_uri
= str
? str
: "";
5074 str
= database_get_data(conf_node
, KEY_LDAP_BASE
, RECDB_QSTRING
);
5075 nickserv_conf
.ldap_base
= str
? str
: "";
5077 str
= database_get_data(conf_node
, KEY_LDAP_DN_FMT
, RECDB_QSTRING
);
5078 nickserv_conf
.ldap_dn_fmt
= str
? str
: "";
5080 str
= database_get_data(conf_node
, KEY_LDAP_VERSION
, RECDB_QSTRING
);
5081 nickserv_conf
.ldap_version
= str
? strtoul(str
, NULL
, 0) : 3;
5083 str
= database_get_data(conf_node
, KEY_LDAP_AUTOCREATE
, RECDB_QSTRING
);
5084 nickserv_conf
.ldap_autocreate
= str
? strtoul(str
, NULL
, 0) : 0;
5086 str
= database_get_data(conf_node
, KEY_LDAP_TIMEOUT
, RECDB_QSTRING
);
5087 nickserv_conf
.ldap_timeout
= str
? strtoul(str
, NULL
, 0) : 5;
5089 str
= database_get_data(conf_node
, KEY_LDAP_ADMIN_DN
, RECDB_QSTRING
);
5090 nickserv_conf
.ldap_admin_dn
= str
? str
: "";
5092 str
= database_get_data(conf_node
, KEY_LDAP_ADMIN_PASS
, RECDB_QSTRING
);
5093 nickserv_conf
.ldap_admin_pass
= str
? str
: "";
5095 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_ACCOUNT
, RECDB_QSTRING
);
5096 nickserv_conf
.ldap_field_account
= str
? str
: "";
5098 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_PASSWORD
, RECDB_QSTRING
);
5099 nickserv_conf
.ldap_field_password
= str
? str
: "";
5101 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_EMAIL
, RECDB_QSTRING
);
5102 nickserv_conf
.ldap_field_email
= str
? str
: "";
5104 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_OSLEVEL
, RECDB_QSTRING
);
5105 nickserv_conf
.ldap_field_oslevel
= str
? str
: "";
5107 str
= database_get_data(conf_node
, KEY_LDAP_OPER_GROUP_DN
, RECDB_QSTRING
);
5108 nickserv_conf
.ldap_oper_group_dn
= str
? str
: "";
5110 str
= database_get_data(conf_node
, KEY_LDAP_OPER_GROUP_LEVEL
, RECDB_QSTRING
);
5111 nickserv_conf
.ldap_oper_group_level
= str
? strtoul(str
, NULL
, 0) : 99;
5113 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_GROUP_MEMBER
, RECDB_QSTRING
);
5114 nickserv_conf
.ldap_field_group_member
= str
? str
: "";
5116 free_string_list(nickserv_conf
.ldap_object_classes
);
5117 strlist
= database_get_data(conf_node
, KEY_LDAP_OBJECT_CLASSES
, RECDB_STRING_LIST
);
5119 strlist
= string_list_copy(strlist
);
5121 strlist
= alloc_string_list(4);
5122 string_list_append(strlist
, strdup("top"));
5124 nickserv_conf
.ldap_object_classes
= strlist
;
5131 nickserv_reclaim(struct userNode
*user
, struct nick_info
*ni
, enum reclaim_action action
) {
5133 char newnick
[NICKLEN
+1];
5142 send_message(user
, nickserv
, "NSMSG_RECLAIM_WARN", ni
->nick
, ni
->owner
->handle
);
5143 send_message(user
, nickserv
, "NSMSG_RECLAIM_HOWTO", ni
->owner
->handle
, nickserv
->nick
, self
->name
, ni
->owner
->handle
);
5145 case RECLAIM_SVSNICK
:
5147 snprintf(newnick
, sizeof(newnick
), "Guest%d", rand()%10000
);
5148 } while (GetUserH(newnick
));
5149 irc_svsnick(nickserv
, user
, newnick
);
5152 msg
= user_find_message(user
, "NSMSG_RECLAIM_KILL");
5153 DelUser(user
, nickserv
, 1, msg
);
5159 nickserv_reclaim_p(void *data
) {
5160 struct userNode
*user
= data
;
5161 struct nick_info
*ni
= get_nick_info(user
->nick
);
5163 nickserv_reclaim(user
, ni
, nickserv_conf
.auto_reclaim_action
);
5167 check_user_nick(struct userNode
*user
, UNUSED_ARG(void *extra
)) {
5168 struct nick_info
*ni
;
5169 user
->modes
&= ~FLAGS_REGNICK
;
5170 if (!(ni
= get_nick_info(user
->nick
)))
5172 if (user
->handle_info
== ni
->owner
) {
5173 user
->modes
|= FLAGS_REGNICK
;
5177 if (nickserv_conf
.warn_nick_owned
)
5178 send_message(user
, nickserv
, "NSMSG_RECLAIM_WARN", ni
->nick
, ni
->owner
->handle
);
5179 send_message(user
, nickserv
, "NSMSG_RECLAIM_HOWTO", ni
->owner
->handle
, nickserv
->nick
, self
->name
, ni
->owner
->handle
);
5180 if (nickserv_conf
.auto_reclaim_action
== RECLAIM_NONE
)
5182 if (nickserv_conf
.auto_reclaim_delay
)
5183 timeq_add(now
+ nickserv_conf
.auto_reclaim_delay
, nickserv_reclaim_p
, user
);
5185 nickserv_reclaim(user
, ni
, nickserv_conf
.auto_reclaim_action
);
5191 handle_account(struct userNode
*user
, const char *stamp
)
5193 struct handle_info
*hi
;
5196 #ifdef WITH_PROTOCOL_P10
5197 time_t timestamp
= 0;
5199 colon
= strchr(stamp
, ':');
5200 if(colon
&& colon
[1])
5203 timestamp
= atoi(colon
+1);
5205 hi
= dict_find(nickserv_handle_dict
, stamp
, NULL
);
5206 if(hi
&& timestamp
&& hi
->registered
!= timestamp
)
5208 log_module(MAIN_LOG
, LOG_WARNING
, "%s using account %s but timestamp does not match %s is not %s.", user
->nick
, stamp
, ctime(×tamp
),
5209 ctime(&hi
->registered
));
5213 hi
= dict_find(nickserv_id_dict
, stamp
, NULL
);
5214 log_module(MAIN_LOG
, LOG_WARNING
, "Using non-P10 code in accounts, not tested at all!");
5218 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
5221 set_user_handle_info(user
, hi
, 0);
5223 log_module(MAIN_LOG
, LOG_WARNING
, "%s had unknown account stamp %s.", user
->nick
, stamp
);
5228 handle_nick_change(struct userNode
*user
, const char *old_nick
, UNUSED_ARG(void *extra
))
5230 struct handle_info
*hi
;
5232 if ((hi
= dict_find(nickserv_allow_auth_dict
, old_nick
, 0))) {
5233 dict_remove(nickserv_allow_auth_dict
, old_nick
);
5234 dict_insert(nickserv_allow_auth_dict
, user
->nick
, hi
);
5236 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
5237 check_user_nick(user
, NULL
);
5241 nickserv_remove_user(struct userNode
*user
, UNUSED_ARG(struct userNode
*killer
), UNUSED_ARG(const char *why
), UNUSED_ARG(void *extra
))
5243 dict_remove(nickserv_allow_auth_dict
, user
->nick
);
5244 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
5245 set_user_handle_info(user
, NULL
, 0);
5248 static struct modcmd
*
5249 nickserv_define_func(const char *name
, modcmd_func_t func
, int min_level
, int must_auth
, int must_be_qualified
)
5251 if (min_level
> 0) {
5253 sprintf(buf
, "%u", min_level
);
5254 if (must_be_qualified
) {
5255 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "level", buf
, "flags", "+qualified,+loghostmask", NULL
);
5257 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "level", buf
, NULL
);
5259 } else if (min_level
== 0) {
5260 if (must_be_qualified
) {
5261 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+helping", NULL
);
5263 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+helping", NULL
);
5266 if (must_be_qualified
) {
5267 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+qualified,+loghostmask", NULL
);
5269 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), NULL
);
5275 nickserv_db_cleanup(UNUSED_ARG(void* extra
))
5277 unreg_del_user_func(nickserv_remove_user
, NULL
);
5278 userList_clean(&curr_helpers
);
5279 policer_params_delete(nickserv_conf
.auth_policer_params
);
5280 dict_delete(nickserv_handle_dict
);
5281 dict_delete(nickserv_nick_dict
);
5282 dict_delete(nickserv_opt_dict
);
5283 dict_delete(nickserv_allow_auth_dict
);
5284 dict_delete(nickserv_email_dict
);
5285 dict_delete(nickserv_id_dict
);
5286 dict_delete(nickserv_conf
.weak_password_dict
);
5287 free(auth_func_list
);
5288 free(auth_func_list_extra
);
5289 free(unreg_func_list
);
5290 free(unreg_func_list_extra
);
5292 free(rf_list_extra
);
5293 free(allowauth_func_list
);
5294 free(allowauth_func_list_extra
);
5295 free(handle_merge_func_list
);
5296 free(handle_merge_func_list_extra
);
5297 free(failpw_func_list
);
5298 free(failpw_func_list_extra
);
5299 if (nickserv_conf
.valid_handle_regex_set
)
5300 regfree(&nickserv_conf
.valid_handle_regex
);
5301 if (nickserv_conf
.valid_nick_regex_set
)
5302 regfree(&nickserv_conf
.valid_nick_regex
);
5305 void handle_loc_auth_oper(struct userNode
*user
, UNUSED_ARG(struct handle_info
*old_handle
), UNUSED_ARG(void *extra
)) {
5306 char *privv
[MAXNUMPARAMS
];
5309 if (!*nickserv_conf
.auto_oper
|| !user
->handle_info
)
5312 if (!IsOper(user
)) {
5313 if (*nickserv_conf
.auto_admin
&& user
->handle_info
->opserv_level
>= opserv_conf_admin_level()) {
5314 if (nickserv_conf
.auto_admin_privs
[0]) {
5315 irc_raw_privs(user
, nickserv_conf
.auto_admin_privs
);
5316 privc
= split_line(strdup(nickserv_conf
.auto_admin_privs
), false, MAXNUMPARAMS
, privv
);
5317 for (i
= 0; i
< privc
; i
++) {
5318 client_modify_priv_by_name(user
, privv
[i
], 1);
5321 irc_umode(user
, nickserv_conf
.auto_admin
);
5322 irc_sno(0x1, "%s (%s@%s) is now an IRC Administrator",
5323 user
->nick
, user
->ident
, user
->hostname
);
5324 send_message(user
, nickserv
, "NSMSG_AUTO_OPER_ADMIN");
5325 } else if (*nickserv_conf
.auto_oper
&& user
->handle_info
->opserv_level
) {
5326 if (nickserv_conf
.auto_oper_privs
[0]) {
5327 irc_raw_privs(user
, nickserv_conf
.auto_oper_privs
);
5328 privc
= split_line(strdup(nickserv_conf
.auto_oper_privs
), false, MAXNUMPARAMS
, privv
);
5329 for (i
= 0; i
< privc
; i
++) {
5330 client_modify_priv_by_name(user
, privv
[i
], 1);
5333 irc_umode(user
, nickserv_conf
.auto_oper
);
5334 irc_sno(0x1, "%s (%s@%s) is now an IRC Operator",
5335 user
->nick
, user
->ident
, user
->hostname
);
5336 send_message(user
, nickserv
, "NSMSG_AUTO_OPER");
5342 init_nickserv(const char *nick
)
5344 struct chanNode
*chan
;
5346 NS_LOG
= log_register_type("NickServ", "file:nickserv.log");
5347 reg_new_user_func(check_user_nick
, NULL
);
5348 reg_nick_change_func(handle_nick_change
, NULL
);
5349 reg_del_user_func(nickserv_remove_user
, NULL
);
5350 reg_account_func(handle_account
);
5351 reg_auth_func(handle_loc_auth_oper
, NULL
);
5353 /* set up handle_inverse_flags */
5354 memset(handle_inverse_flags
, 0, sizeof(handle_inverse_flags
));
5355 for (i
=0; handle_flags
[i
]; i
++) {
5356 handle_inverse_flags
[(unsigned char)handle_flags
[i
]] = i
+ 1;
5357 flag_access_levels
[i
] = 0;
5360 conf_register_reload(nickserv_conf_read
);
5361 nickserv_opt_dict
= dict_new();
5362 nickserv_email_dict
= dict_new();
5364 dict_set_free_keys(nickserv_email_dict
, free
);
5365 dict_set_free_data(nickserv_email_dict
, nickserv_free_email_addr
);
5367 nickserv_module
= module_register("NickServ", NS_LOG
, "nickserv.help", NULL
);
5368 /* Removed qualified_host as default requirement for AUTH, REGISTER, PASS, etc. nets
5369 * can enable it per command using modcmd. (its a shitty default IMO, and now in 1.3
5370 * a big pain to disable since its nolonger in the config file. ) -Rubin
5372 modcmd_register(nickserv_module
, "AUTH", cmd_auth
, 2, MODCMD_KEEP_BOUND
, "flags", "+loghostmask", NULL
);
5373 nickserv_define_func("ALLOWAUTH", cmd_allowauth
, 0, 1, 0);
5374 nickserv_define_func("REGISTER", cmd_register
, -1, 0, 0);
5375 nickserv_define_func("OREGISTER", cmd_oregister
, 0, 1, 0);
5376 nickserv_define_func("UNREGISTER", cmd_unregister
, -1, 1, 0);
5377 nickserv_define_func("OUNREGISTER", cmd_ounregister
, 0, 1, 0);
5378 nickserv_define_func("ADDMASK", cmd_addmask
, -1, 1, 0);
5379 nickserv_define_func("OADDMASK", cmd_oaddmask
, 0, 1, 0);
5380 nickserv_define_func("DELMASK", cmd_delmask
, -1, 1, 0);
5381 nickserv_define_func("ODELMASK", cmd_odelmask
, 0, 1, 0);
5382 nickserv_define_func("ADDSSLFP", cmd_addsslfp
, -1, 1, 0);
5383 nickserv_define_func("OADDSSLFP", cmd_oaddsslfp
, 0, 1, 0);
5384 nickserv_define_func("DELSSLFP", cmd_delsslfp
, -1, 1, 0);
5385 nickserv_define_func("ODELSSLFP", cmd_odelsslfp
, 0, 1, 0);
5386 nickserv_define_func("PASS", cmd_pass
, -1, 1, 0);
5387 nickserv_define_func("SET", cmd_set
, -1, 1, 0);
5388 nickserv_define_func("OSET", cmd_oset
, 0, 1, 0);
5389 nickserv_define_func("ACCOUNTINFO", cmd_handleinfo
, -1, 0, 0);
5390 nickserv_define_func("USERINFO", cmd_userinfo
, -1, 1, 0);
5391 nickserv_define_func("RENAME", cmd_rename_handle
, -1, 1, 0);
5392 nickserv_define_func("VACATION", cmd_vacation
, -1, 1, 0);
5393 nickserv_define_func("MERGE", cmd_merge
, 750, 1, 0);
5394 if (!nickserv_conf
.disable_nicks
) {
5395 /* nick management commands */
5396 nickserv_define_func("REGNICK", cmd_regnick
, -1, 1, 0);
5397 nickserv_define_func("OREGNICK", cmd_oregnick
, 0, 1, 0);
5398 nickserv_define_func("UNREGNICK", cmd_unregnick
, -1, 1, 0);
5399 nickserv_define_func("OUNREGNICK", cmd_ounregnick
, 0, 1, 0);
5400 nickserv_define_func("NICKINFO", cmd_nickinfo
, -1, 1, 0);
5401 nickserv_define_func("RECLAIM", cmd_reclaim
, -1, 1, 0);
5403 if (nickserv_conf
.email_enabled
) {
5404 nickserv_define_func("AUTHCOOKIE", cmd_authcookie
, -1, 0, 0);
5405 nickserv_define_func("RESETPASS", cmd_resetpass
, -1, 0, 0);
5406 nickserv_define_func("COOKIE", cmd_cookie
, -1, 0, 0);
5407 nickserv_define_func("DELCOOKIE", cmd_delcookie
, -1, 1, 0);
5408 nickserv_define_func("ODELCOOKIE", cmd_odelcookie
, 0, 1, 0);
5409 dict_insert(nickserv_opt_dict
, "EMAIL", opt_email
);
5411 nickserv_define_func("GHOST", cmd_ghost
, -1, 1, 0);
5412 /* ignore commands */
5413 nickserv_define_func("ADDIGNORE", cmd_addignore
, -1, 1, 0);
5414 nickserv_define_func("OADDIGNORE", cmd_oaddignore
, 0, 1, 0);
5415 nickserv_define_func("DELIGNORE", cmd_delignore
, -1, 1, 0);
5416 nickserv_define_func("ODELIGNORE", cmd_odelignore
, 0, 1, 0);
5417 /* miscellaneous commands */
5418 nickserv_define_func("STATUS", cmd_status
, -1, 0, 0);
5419 nickserv_define_func("SEARCH", cmd_search
, 100, 1, 0);
5420 nickserv_define_func("SEARCH UNREGISTER", NULL
, 800, 1, 0);
5421 nickserv_define_func("MERGEDB", cmd_mergedb
, 999, 1, 0);
5422 nickserv_define_func("CHECKPASS", cmd_checkpass
, 601, 1, 0);
5423 nickserv_define_func("CHECKEMAIL", cmd_checkemail
, 0, 1, 0);
5425 dict_insert(nickserv_opt_dict
, "INFO", opt_info
);
5426 dict_insert(nickserv_opt_dict
, "WIDTH", opt_width
);
5427 dict_insert(nickserv_opt_dict
, "TABLEWIDTH", opt_tablewidth
);
5428 dict_insert(nickserv_opt_dict
, "COLOR", opt_color
);
5429 dict_insert(nickserv_opt_dict
, "PRIVMSG", opt_privmsg
);
5430 dict_insert(nickserv_opt_dict
, "AUTOHIDE", opt_autohide
);
5431 dict_insert(nickserv_opt_dict
, "STYLE", opt_style
);
5432 dict_insert(nickserv_opt_dict
, "PASS", opt_password
);
5433 dict_insert(nickserv_opt_dict
, "PASSWORD", opt_password
);
5434 dict_insert(nickserv_opt_dict
, "FLAGS", opt_flags
);
5435 dict_insert(nickserv_opt_dict
, "ACCESS", opt_level
);
5436 dict_insert(nickserv_opt_dict
, "LEVEL", opt_level
);
5437 dict_insert(nickserv_opt_dict
, "EPITHET", opt_epithet
);
5438 dict_insert(nickserv_opt_dict
, "NOTE", opt_note
);
5439 if (nickserv_conf
.titlehost_suffix
) {
5440 dict_insert(nickserv_opt_dict
, "TITLE", opt_title
);
5441 dict_insert(nickserv_opt_dict
, "FAKEHOST", opt_fakehost
);
5443 dict_insert(nickserv_opt_dict
, "ANNOUNCEMENTS", opt_announcements
);
5444 dict_insert(nickserv_opt_dict
, "MAXLOGINS", opt_maxlogins
);
5445 dict_insert(nickserv_opt_dict
, "ADVANCED", opt_advanced
);
5446 dict_insert(nickserv_opt_dict
, "LANGUAGE", opt_language
);
5447 dict_insert(nickserv_opt_dict
, "KARMA", opt_karma
);
5449 nickserv_handle_dict
= dict_new();
5450 dict_set_free_keys(nickserv_handle_dict
, free
);
5451 dict_set_free_data(nickserv_handle_dict
, free_handle_info
);
5453 nickserv_id_dict
= dict_new();
5454 dict_set_free_keys(nickserv_id_dict
, free
);
5456 nickserv_nick_dict
= dict_new();
5457 dict_set_free_data(nickserv_nick_dict
, free
);
5459 nickserv_allow_auth_dict
= dict_new();
5461 userList_init(&curr_helpers
);
5464 const char *modes
= conf_get_data("services/nickserv/modes", RECDB_QSTRING
);
5465 nickserv
= AddLocalUser(nick
, nick
, NULL
, "Nick Services", modes
);
5466 nickserv_service
= service_register(nickserv
);
5468 saxdb_register("NickServ", nickserv_saxdb_read
, nickserv_saxdb_write
);
5469 reg_exit_func(nickserv_db_cleanup
, NULL
);
5470 if(nickserv_conf
.handle_expire_frequency
)
5471 timeq_add(now
+ nickserv_conf
.handle_expire_frequency
, expire_handles
, NULL
);
5473 if(autojoin_channels
&& nickserv
) {
5474 for (i
= 0; i
< autojoin_channels
->used
; i
++) {
5475 chan
= AddChannel(autojoin_channels
->list
[i
], now
, "+nt", NULL
, NULL
);
5476 AddChannelUser(nickserv
, chan
)->modes
|= MODE_CHANOP
;
5480 ldap_do_init(nickserv_conf
);
5483 message_register_table(msgtab
);