1 /* nickserv.c - Nick/authentication service
2 * Copyright 2000-2004 srvx Development Team
4 * This file is part of x3.
6 * x3 is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with srvx; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 #include "opserv.h" /* for gag_create(), opserv_bad_channel() */
32 #include <tre/regex.h>
38 #define NICKSERV_CONF_NAME "services/nickserv"
40 #define KEY_DISABLE_NICKS "disable_nicks"
41 #define KEY_DEFAULT_HOSTMASK "default_hostmask"
42 #define KEY_NICKS_PER_HANDLE "nicks_per_handle"
43 #define KEY_NICKS_PER_ACCOUNT "nicks_per_account"
44 #define KEY_PASSWORD_MIN_LENGTH "password_min_length"
45 #define KEY_PASSWORD_MIN_DIGITS "password_min_digits"
46 #define KEY_PASSWORD_MIN_UPPER "password_min_upper"
47 #define KEY_PASSWORD_MIN_LOWER "password_min_lower"
48 #define KEY_VALID_HANDLE_REGEX "valid_handle_regex"
49 #define KEY_VALID_ACCOUNT_REGEX "valid_account_regex"
50 #define KEY_VALID_NICK_REGEX "valid_nick_regex"
51 #define KEY_VALID_FAKEHOST_REGEX "valid_fakehost_regex"
52 #define KEY_DB_BACKUP_FREQ "db_backup_freq"
53 #define KEY_MODOPER_LEVEL "modoper_level"
54 #define KEY_SET_EPITHET_LEVEL "set_epithet_level"
55 #define KEY_SET_TITLE_LEVEL "set_title_level"
56 #define KEY_SET_FAKEHOST_LEVEL "set_fakehost_level"
57 #define KEY_DENIED_FAKEHOST_WORDS "denied_fakehost_words"
58 #define KEY_TITLEHOST_SUFFIX "titlehost_suffix"
59 #define KEY_AUTO_OPER "auto_oper"
60 #define KEY_AUTO_ADMIN "auto_admin"
61 #define KEY_AUTO_OPER_PRIVS "auto_oper_privs"
62 #define KEY_AUTO_ADMIN_PRIVS "auto_admin_privs"
63 #define KEY_FLAG_LEVELS "flag_levels"
64 #define KEY_HANDLE_EXPIRE_FREQ "handle_expire_freq"
65 #define KEY_ACCOUNT_EXPIRE_FREQ "account_expire_freq"
66 #define KEY_HANDLE_EXPIRE_DELAY "handle_expire_delay"
67 #define KEY_ACCOUNT_EXPIRE_DELAY "account_expire_delay"
68 #define KEY_NOCHAN_HANDLE_EXPIRE_DELAY "nochan_handle_expire_delay"
69 #define KEY_NOCHAN_ACCOUNT_EXPIRE_DELAY "nochan_account_expire_delay"
70 #define KEY_DICT_FILE "dict_file"
71 #define KEY_NICK "nick"
72 #define KEY_LANGUAGE "language"
73 #define KEY_AUTOGAG_ENABLED "autogag_enabled"
74 #define KEY_AUTOGAG_DURATION "autogag_duration"
75 #define KEY_AUTH_POLICER "auth_policer"
76 #define KEY_EMAIL_VISIBLE_LEVEL "email_visible_level"
77 #define KEY_EMAIL_ENABLED "email_enabled"
78 #define KEY_EMAIL_REQUIRED "email_required"
79 #define KEY_SYNC_LOG "sync_log"
80 #define KEY_COOKIE_TIMEOUT "cookie_timeout"
81 #define KEY_ACCOUNTS_PER_EMAIL "accounts_per_email"
82 #define KEY_EMAIL_SEARCH_LEVEL "email_search_level"
83 #define KEY_DEFAULT_STYLE "default_style"
84 #define KEY_OUNREGISTER_INACTIVE "ounregister_inactive"
85 #define KEY_OUNREGISTER_FLAGS "ounregister_flags"
88 #define KEY_PASSWD "passwd"
89 #define KEY_NICKS "nicks"
90 #define KEY_MASKS "masks"
91 #define KEY_SSLFPS "sslfps"
92 #define KEY_IGNORES "ignores"
93 #define KEY_OPSERV_LEVEL "opserv_level"
94 #define KEY_FLAGS "flags"
95 #define KEY_REGISTER_ON "register"
96 #define KEY_LAST_SEEN "lastseen"
97 #define KEY_INFO "info"
98 #define KEY_USERLIST_STYLE "user_style"
99 #define KEY_SCREEN_WIDTH "screen_width"
100 #define KEY_LAST_AUTHED_HOST "last_authed_host"
101 #define KEY_LAST_QUIT_HOST "last_quit_host"
102 #define KEY_EMAIL_ADDR "email_addr"
103 #define KEY_COOKIE "cookie"
104 #define KEY_COOKIE_DATA "data"
105 #define KEY_COOKIE_TYPE "type"
106 #define KEY_COOKIE_EXPIRES "expires"
107 #define KEY_ACTIVATION "activation"
108 #define KEY_PASSWORD_CHANGE "password change"
109 #define KEY_EMAIL_CHANGE "email change"
110 #define KEY_ALLOWAUTH "allowauth"
111 #define KEY_EPITHET "epithet"
112 #define KEY_TABLE_WIDTH "table_width"
113 #define KEY_ANNOUNCEMENTS "announcements"
114 #define KEY_MAXLOGINS "maxlogins"
115 #define KEY_FAKEHOST "fakehost"
116 #define KEY_NOTE_NOTE "note"
117 #define KEY_NOTE_SETTER "setter"
118 #define KEY_NOTE_DATE "date"
119 #define KEY_KARMA "karma"
120 #define KEY_FORCE_HANDLES_LOWERCASE "force_handles_lowercase"
122 #define KEY_LDAP_ENABLE "ldap_enable"
125 #define KEY_LDAP_URI "ldap_uri"
126 #define KEY_LDAP_BASE "ldap_base"
127 #define KEY_LDAP_DN_FMT "ldap_dn_fmt"
128 #define KEY_LDAP_VERSION "ldap_version"
129 #define KEY_LDAP_AUTOCREATE "ldap_autocreate"
130 #define KEY_LDAP_ADMIN_DN "ldap_admin_dn"
131 #define KEY_LDAP_ADMIN_PASS "ldap_admin_pass"
132 #define KEY_LDAP_FIELD_ACCOUNT "ldap_field_account"
133 #define KEY_LDAP_FIELD_PASSWORD "ldap_field_password"
134 #define KEY_LDAP_FIELD_EMAIL "ldap_field_email"
135 #define KEY_LDAP_FIELD_OSLEVEL "ldap_field_oslevel"
136 #define KEY_LDAP_OBJECT_CLASSES "ldap_object_classes"
137 #define KEY_LDAP_OPER_GROUP_DN "ldap_oper_group_dn"
138 #define KEY_LDAP_OPER_GROUP_LEVEL "ldap_oper_group_level"
139 #define KEY_LDAP_FIELD_GROUP_MEMBER "ldap_field_group_member"
140 #define KEY_LDAP_TIMEOUT "ldap_timeout"
143 #define NICKSERV_VALID_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
145 #define NICKSERV_FUNC(NAME) MODCMD_FUNC(NAME)
146 #define OPTION_FUNC(NAME) int NAME(UNUSED_ARG(struct svccmd *cmd), struct userNode *user, struct handle_info *hi, UNUSED_ARG(unsigned int override), unsigned int argc, char *argv[])
147 typedef OPTION_FUNC(option_func_t
);
149 DEFINE_LIST(handle_info_list
, struct handle_info
*)
151 #define NICKSERV_MIN_PARMS(N) do { \
153 reply("MSG_MISSING_PARAMS", argv[0]); \
154 svccmd_send_help_brief(user, nickserv, cmd); \
158 struct userNode
*nickserv
;
159 struct userList curr_helpers
;
160 const char *handle_flags
= HANDLE_FLAGS
;
162 extern struct string_list
*autojoin_channels
;
163 static struct module *nickserv_module
;
164 static struct service
*nickserv_service
;
165 static struct log_type
*NS_LOG
;
166 dict_t nickserv_handle_dict
; /* contains struct handle_info* */
167 static dict_t nickserv_id_dict
; /* contains struct handle_info* */
168 static dict_t nickserv_nick_dict
; /* contains struct nick_info* */
169 static dict_t nickserv_opt_dict
; /* contains option_func_t* */
170 static dict_t nickserv_allow_auth_dict
; /* contains struct handle_info* */
171 static dict_t nickserv_email_dict
; /* contains struct handle_info_list*, indexed by email addr */
172 static char handle_inverse_flags
[256];
173 static unsigned int flag_access_levels
[32];
174 static const struct message_entry msgtab
[] = {
175 { "NSMSG_NO_ANGLEBRACKETS", "The < and > in help indicate that that word is a required parameter, but DO NOT actually type them in messages to me." },
176 { "NSMSG_HANDLE_EXISTS", "Account $b%s$b is already registered." },
177 { "NSMSG_HANDLE_TOLONG", "The account name %s is too long. Account names must be %lu characters or less."},
178 { "NSMSG_PASSWORD_SHORT", "Your password must be at least %lu characters long." },
179 { "NSMSG_PASSWORD_ACCOUNT", "Your password may not be the same as your account name." },
180 { "NSMSG_PASSWORD_DICTIONARY", "Your password is too simple. You must choose a password that is not just a word or name." },
181 { "NSMSG_PASSWORD_READABLE", "Your password must have at least %lu digit(s), %lu capital letter(s), and %lu lower-case letter(s)." },
182 { "NSMSG_LDAP_FAIL", "There was a problem in contacting the account server (ldap): %s. Please try again later." },
183 { "NSMSG_LDAP_FAIL_ADD", "There was a problem in adding account %s to ldap: %s." },
184 { "NSMSG_LDAP_FAIL_SEND_EMAIL", "There was a problem in storing your email address in the account server (ldap): %s. Please try again later." },
185 { "NSMSG_LDAP_FAIL_GET_EMAIL", "There was a problem in retrieving your email address from the account server (ldap): %s. Please try again later." },
186 { "NSMSG_PARTIAL_REGISTER", "Account has been registered to you; nick was already registered to someone else." },
187 { "NSMSG_OREGISTER_VICTIM", "%s has registered a new account for you (named %s)." },
188 { "NSMSG_OREGISTER_H_SUCCESS", "Account has been registered." },
189 { "NSMSG_REGISTER_H_SUCCESS", "Account has been registered to you." },
190 { "NSMSG_REGISTER_HN_SUCCESS", "Account and nick have been registered to you." },
191 { "NSMSG_REQUIRE_OPER", "You must be an $bIRC Operator$b to register the first account." },
192 { "NSMSG_ROOT_HANDLE", "Account %s has been granted $broot-level privileges$b." },
193 { "NSMSG_USE_COOKIE_REGISTER", "To activate your account, you must check your email for the \"cookie\" that has been mailed to it. When you have it, use the $bcookie$b command to complete registration." },
194 { "NSMSG_USE_COOKIE_RESETPASS", "A cookie has been mailed to your account's email address. You must check your email and use the $bcookie$b command to confirm the password change." },
195 { "NSMSG_USE_COOKIE_EMAIL_1", "A cookie has been mailed to the new address you requested. To finish setting your email address, please check your email for the cookie and use the $bcookie$b command to verify." },
196 { "NSMSG_USE_COOKIE_EMAIL_2", "A cookie has been generated, and half mailed to each your old and new addresses. To finish changing your email address, please check your email for the cookie and use the $bcookie$b command to verify." },
197 { "NSMSG_USE_COOKIE_AUTH", "A cookie has been generated and sent to your email address. Once you have checked your email and received the cookie, auth using the $bcookie$b command." },
198 { "NSMSG_COOKIE_LIVE", "Account $b%s$b already has a cookie active. Please either finish using that cookie, wait for it to expire, or auth to the account and use the $bdelcookie$b command." },
199 { "NSMSG_EMAIL_UNACTIVATED", "That email address already has an unused cookie outstanding. Please use the cookie or wait for it to expire." },
200 { "NSMSG_NO_COOKIE", "Your account does not have any cookie issued right now." },
201 { "NSMSG_NO_COOKIE_FOREIGN", "The account $b%s$b does not have any cookie issued right now." },
202 { "NSMSG_CANNOT_COOKIE", "You cannot use that kind of cookie when you are logged in." },
203 { "NSMSG_BAD_COOKIE", "That cookie is not the right one. Please make sure you are copying it EXACTLY from the email; it is case-sensitive, so $bABC$b is different from $babc$b." },
204 { "NSMSG_HANDLE_ACTIVATED", "Your account is now activated (with the password you entered when you registered). You are now authenticated to your account." },
205 { "NSMSG_PASSWORD_CHANGED", "You have successfully changed your password to what you requested with the $bresetpass$b command." },
206 { "NSMSG_EMAIL_PROHIBITED", "%s may not be used as an email address: %s" },
207 { "NSMSG_EMAIL_OVERUSED", "That email address already has an account. Use RESETPASS if you forgot your password." },
208 { "NSMSG_EMAIL_SAME", "That is the email address already there; no need to change it." },
209 { "NSMSG_EMAIL_CHANGED", "You have successfully changed your email address." },
210 { "NSMSG_BAD_COOKIE_TYPE", "Your account had bad cookie type %d; sorry. I am confused. Please report this bug." },
211 { "NSMSG_MUST_TIME_OUT", "You must wait for cookies of that type to time out." },
212 { "NSMSG_ATE_COOKIE", "I ate the cookie for your account. You may now have another." },
213 { "NSMSG_ATE_FOREIGN_COOKIE", "I ate the cookie for account $b%s$b. It may now have another." },
214 { "NSMSG_USE_RENAME", "You are already authenticated to account $b%s$b -- contact the support staff to rename your account." },
215 { "NSMSG_ALREADY_REGISTERING", "You have already used $bREGISTER$b once this session; you may not use it again." },
216 { "NSMSG_REGISTER_BAD_NICKMASK", "You must provide a hostmask, or online nick to generate one automatically. (or set a default hostmask in the config such as *@*)." },
217 { "NSMSG_NICK_NOT_REGISTERED", "Nick $b%s$b has not been registered to any account." },
218 { "NSMSG_HANDLE_NOT_FOUND", "Could not find your account -- did you register yet?" },
219 { "NSMSG_ALREADY_AUTHED", "You are already authed to account $b%s$b; you must reconnect to auth to a different account." },
220 { "NSMSG_USE_AUTHCOOKIE", "Your hostmask is not valid for account $b%1$s$b. Please use the $bauthcookie$b command to grant yourself access. (/msg $S authcookie %1$s)" },
221 { "NSMSG_HOSTMASK_INVALID", "Your hostmask is not valid for account $b%s$b." },
222 { "NSMSG_USER_IS_SERVICE", "$b%s$b is a network service; you can only use that command on real users." },
223 { "NSMSG_USER_PREV_AUTH", "$b%s$b is already authenticated." },
224 { "NSMSG_USER_PREV_STAMP", "$b%s$b has authenticated to an account once and cannot authenticate again." },
225 { "NSMSG_BAD_MAX_LOGINS", "MaxLogins must be at most %d." },
226 { "NSMSG_BAD_ADVANCED", "Advanced must be either 1 to enable it or 0 to disable it." },
227 { "NSMSG_LANGUAGE_NOT_FOUND", "Language $b%s$b is not supported; $b%s$b was the closest available match." },
228 { "NSMSG_MAX_LOGINS", "Your account already has its limit of %d user(s) logged in." },
229 { "NSMSG_STAMPED_REGISTER", "You have already authenticated to an account once this session; you may not register a new account." },
230 { "NSMSG_STAMPED_AUTH", "You have already authenticated to an account once this session; you may not authenticate to another." },
231 { "NSMSG_STAMPED_RESETPASS", "You have already authenticated to an account once this session; you may not reset your password to authenticate again." },
232 { "NSMSG_STAMPED_AUTHCOOKIE", "You have already authenticated to an account once this session; you may not use a cookie to authenticate to another account." },
233 { "NSMSG_TITLE_INVALID", "Titles may contain only a-z, A-Z, 0-9, and '-'. Please choose another." },
234 { "NSMSG_TITLE_TRUNCATED", "That title combined with the user's account name would result in a truncated host; please choose a shorter title." },
235 { "NSMSG_FAKEHOST_INVALID", "Fake hosts must be shorter than %d characters and cannot start with a dot." },
236 { "NSMSG_HANDLEINFO_ON", "$bAccount Information for %s$b" },
237 { "NSMSG_HANDLEINFO_END", "----------End of Account Info-----------" },
238 { "NSMSG_HANDLEINFO_ID", "Account ID: %lu" },
239 { "NSMSG_HANDLEINFO_REGGED", "Registered on: %s" },
240 { "NSMSG_HANDLEINFO_LASTSEEN", "Last seen: %s" },
241 { "NSMSG_HANDLEINFO_LASTSEEN_NOW", "Last seen: Right now!" },
242 { "NSMSG_HANDLEINFO_KARMA", "Karma: %d" },
243 { "NSMSG_HANDLEINFO_VACATION", "On vacation." },
244 { "NSMSG_HANDLEINFO_EMAIL_ADDR", "Email address: %s" },
245 { "NSMSG_HANDLEINFO_COOKIE_ACTIVATION", "Cookie: There is currently an activation cookie issued for this account" },
246 { "NSMSG_HANDLEINFO_COOKIE_PASSWORD", "Cookie: There is currently a password change cookie issued for this account" },
247 { "NSMSG_HANDLEINFO_COOKIE_EMAIL", "Cookie: There is currently an email change cookie issued for this account" },
248 { "NSMSG_HANDLEINFO_COOKIE_ALLOWAUTH", "Cookie: There is currently an allowauth cookie issued for this account" },
249 { "NSMSG_HANDLEINFO_COOKIE_UNKNOWN", "Cookie: There is currently an unknown cookie issued for this account" },
250 { "NSMSG_HANDLEINFO_INFOLINE", "Infoline: %s" },
251 { "NSMSG_HANDLEINFO_FLAGS", "Flags: %s" },
252 { "NSMSG_HANDLEINFO_EPITHET", "Epithet: %s" },
253 { "NSMSG_HANDLEINFO_NOTE", "Note (by %s on %s): %s " },
254 { "NSMSG_HANDLEINFO_FAKEHOST", "Fake host: %s" },
255 { "NSMSG_INVALID_KARMA", "$b%s$b is not a valid karma modifier." },
256 { "NSMSG_SET_KARMA", "$bKARMA: $b%d$b" },
257 { "NSMSG_HANDLEINFO_LAST_HOST", "Last quit hostmask: %s" },
258 { "NSMSG_HANDLEINFO_LAST_HOST_UNKNOWN", "Last quit hostmask: Unknown" },
259 { "NSMSG_HANDLEINFO_NICKS", "Nickname(s): %s" },
260 { "NSMSG_HANDLEINFO_MASKS", "Hostmask(s): %s" },
261 { "NSMSG_HANDLEINFO_SSLFPS", "SSL Fingerprints(s): %s" },
262 { "NSMSG_HANDLEINFO_IGNORES", "Ignore(s): %s" },
263 { "NSMSG_HANDLEINFO_CHANNELS", "Channel(s): %s" },
264 { "NSMSG_HANDLEINFO_CURRENT", "Current nickname(s): %s" },
265 { "NSMSG_HANDLEINFO_DNR", "Do-not-register (by %s): %s" },
266 { "NSMSG_USERINFO_AUTHED_AS", "$b%s$b is authenticated to account $b%s$b." },
267 { "NSMSG_USERINFO_NOT_AUTHED", "$b%s$b is not authenticated to any account." },
268 { "NSMSG_NICKINFO_OWNER", "Nick $b%s$b is owned by account $b%s$b." },
269 { "NSMSG_PASSWORD_INVALID", "Incorrect password; please try again." },
270 { "NSMSG_PLEASE_SET_EMAIL", "We now require email addresses for users. Please use the $bset email$b command to set your email address!" },
271 { "NSMSG_WEAK_PASSWORD", "WARNING: You are using a password that is considered weak (easy to guess). It is STRONGLY recommended you change it (now, if not sooner) by typing \"/msg $S@$s PASS oldpass newpass\" (with your current password and a new password)." },
272 { "NSMSG_HANDLE_SUSPENDED", "Your $b$N$b account has been suspended; you may not use it." },
273 { "NSMSG_AUTH_SUCCESS", "I recognize you." },
274 { "NSMSG_ALLOWAUTH_STAFF", "$b%s$b is a helper or oper; please use $bstaff$b after the account name to allowauth." },
275 { "NSMSG_AUTH_ALLOWED", "User $b%s$b may now authenticate to account $b%s$b." },
276 { "NSMSG_AUTH_ALLOWED_MSG", "You may now authenticate to account $b%s$b by typing $b/msg $N@$s auth %s password$b (using your password). If you will be using this computer regularly, please type $b/msg $N addmask$b (AFTER you auth) to permanently add your hostmask." },
277 { "NSMSG_AUTH_ALLOWED_EMAIL", "You may also (after you auth) type $b/msg $N set email user@your.isp$b to set an email address. This will let you use the $bauthcookie$b command to be authenticated in the future." },
278 { "NSMSG_AUTH_NORMAL_ONLY", "User $b%s$b may now only authenticate to accounts with matching hostmasks." },
279 { "NSMSG_AUTH_UNSPECIAL", "User $b%s$b did not have any special auth allowance." },
280 { "NSMSG_MUST_AUTH", "You must be authenticated first." },
281 { "NSMSG_TOO_MANY_NICKS", "You have already registered the maximum permitted number of nicks." },
282 { "NSMSG_NICK_EXISTS", "Nick $b%s$b already registered." },
283 { "NSMSG_REGNICK_SUCCESS", "Nick $b%s$b has been registered to you." },
284 { "NSMSG_OREGNICK_SUCCESS", "Nick $b%s$b has been registered to account $b%s$b." },
285 { "NSMSG_PASS_SUCCESS", "Password changed." },
286 { "NSMSG_MASK_INVALID", "$b%s$b is an invalid hostmask." },
287 { "NSMSG_ADDMASK_ALREADY", "$b%s$b is already a hostmask in your account." },
288 { "NSMSG_ADDMASK_SUCCESS", "Hostmask %s added." },
289 { "NSMSG_ADDIGNORE_ALREADY", "$b%s$b is already an ignored hostmask in your account." },
290 { "NSMSG_ADDIGNORE_SUCCESS", "Hostmask %s added." },
291 { "NSMSG_ADDSSLFP_ALREADY", "$b%s$b is already an SSL fingerprint in your account." },
292 { "NSMSG_ADDSSLFP_SUCCESS", "SSL fingerprint %s added." },
293 { "NSMSG_DELMASK_NOTLAST", "You may not delete your last hostmask." },
294 { "NSMSG_DELMASK_SUCCESS", "Hostmask %s deleted." },
295 { "NSMSG_DELMASK_NOT_FOUND", "Unable to find mask to be deleted." },
296 { "NSMSG_DELSSLFP_SUCCESS", "SSL fingerprint %s deleted." },
297 { "NSMSG_DELSSLFP_NOT_FOUND", "Unable to find SSL fingerprint to be deleted." },
298 { "NSMSG_OPSERV_LEVEL_BAD", "You may not promote another oper above your level." },
299 { "NSMSG_USE_CMD_PASS", "Please use the PASS command to change your password." },
300 { "NSMSG_UNKNOWN_NICK", "I know nothing about nick $b%s$b." },
301 { "NSMSG_NOT_YOUR_NICK", "The nick $b%s$b is not registered to you." },
302 { "NSMSG_NICK_USER_YOU", "I will not let you kill yourself." },
303 { "NSMSG_UNREGNICK_SUCCESS", "Nick $b%s$b has been unregistered." },
304 { "NSMSG_UNREGISTER_SUCCESS", "Account $b%s$b has been unregistered." },
305 { "NSMSG_UNREGISTER_NICKS_SUCCESS", "Account $b%s$b and all its nicks have been unregistered." },
306 { "NSMSG_UNREGISTER_MUST_FORCE", "Account $b%s$b is not inactive or has special flags set; use FORCE to unregister it." },
307 { "NSMSG_UNREGISTER_CANNOT_FORCE", "Account $b%s$b is not inactive or has special flags set; have an IRCOp use FORCE to unregister it." },
308 { "NSMSG_UNREGISTER_NODELETE", "Account $b%s$b is protected from unregistration." },
309 { "NSMSG_HANDLE_STATS", "There are %d nicks registered to your account." },
310 { "NSMSG_HANDLE_NONE", "You are not authenticated against any account." },
311 { "NSMSG_GLOBAL_STATS", "There are %d accounts and %d nicks registered globally." },
312 { "NSMSG_GLOBAL_STATS_NONICK", "There are %d accounts registered." },
313 { "NSMSG_CANNOT_GHOST_SELF", "You may not ghost-kill yourself." },
314 { "NSMSG_CANNOT_GHOST_USER", "$b%s$b is not authed to your account; you may not ghost-kill them." },
315 { "NSMSG_GHOST_KILLED", "$b%s$b has been killed as a ghost." },
316 { "NSMSG_ON_VACATION", "You are now on vacation. Your account will be preserved until you authenticate again." },
317 { "NSMSG_NO_ACCESS", "Access denied." },
318 { "NSMSG_INVALID_FLAG", "$b%c$b is not a valid $N account flag." },
319 { "NSMSG_SET_FLAG", "Applied flags $b%s$b to %s's $N account." },
320 { "NSMSG_FLAG_PRIVILEGED", "You have insufficient access to set flag %c." },
321 { "NSMSG_DB_UNREADABLE", "Unable to read database file %s; check the log for more information." },
322 { "NSMSG_DB_MERGED", "$N merged DB from %s (in "FMT_TIME_T
".%03lu seconds)." },
323 { "NSMSG_HANDLE_CHANGED", "$b%s$b's account name has been changed to $b%s$b." },
324 { "NSMSG_BAD_HANDLE", "Account $b%s$b is not allowed because it is reserved, is too long, or contains invalid characters." },
325 { "NSMSG_BAD_NICK", "Nickname $b%s$b not registered because it is in use by a network service, is too long, or contains invalid characters." },
326 { "NSMSG_BAD_EMAIL_ADDR", "Please use a well-formed email address." },
327 { "NSMSG_FAIL_RENAME", "Account $b%s$b not renamed to $b%s$b because it is in use by a network services, or contains invalid characters." },
328 { "NSMSG_ACCOUNT_SEARCH_RESULTS", "The following accounts were found:" },
329 { "NSMSG_SEARCH_MATCH", "Match: %s" },
330 { "NSMSG_INVALID_ACTION", "%s is an invalid search action." },
331 { "NSMSG_CANNOT_MERGE_SELF", "You cannot merge account $b%s$b with itself." },
332 { "NSMSG_HANDLES_MERGED", "Merged account $b%s$b into $b%s$b." },
333 { "NSMSG_RECLAIM_WARN", "%s is a registered nick - you must auth to account %s or change your nick." },
334 { "NSMSG_RECLAIM_HOWTO", "To auth to account %s you must use /msg %s@%s AUTH %s <password>" },
335 { "NSMSG_RECLAIM_KILL", "Unauthenticated user of nick." },
336 { "NSMSG_RECLAIMED_NONE", "You cannot manually reclaim a nick." },
337 { "NSMSG_RECLAIMED_WARN", "Sent a request for %s to change their nick." },
338 { "NSMSG_RECLAIMED_SVSNICK", "Forcibly changed %s's nick." },
339 { "NSMSG_RECLAIMED_KILL", "Disconnected %s from the network." },
340 { "NSMSG_CLONE_AUTH", "Warning: %s (%s@%s) authed to your account." },
341 { "NSMSG_SETTING_LIST", "$b$N account settings$b" },
342 { "NSMSG_SETTING_LIST_HEADER", "----------------------------------------" },
343 { "NSMSG_SETTING_LIST_END", "-------------End Of Settings------------" },
344 { "NSMSG_INVALID_OPTION", "$b%s$b is an invalid account setting." },
345 { "NSMSG_INVALID_ANNOUNCE", "$b%s$b is an invalid announcements value." },
346 { "NSMSG_SET_INFO", "$bINFO: $b%s" },
347 { "NSMSG_SET_WIDTH", "$bWIDTH: $b%d" },
348 { "NSMSG_SET_TABLEWIDTH", "$bTABLEWIDTH: $b%d" },
349 { "NSMSG_SET_COLOR", "$bCOLOR: $b%s" },
350 { "NSMSG_SET_PRIVMSG", "$bPRIVMSG: $b%s" },
351 { "NSMSG_SET_STYLE", "$bSTYLE: $b%s" },
352 { "NSMSG_SET_ANNOUNCEMENTS", "$bANNOUNCEMENTS: $b%s" },
353 { "NSMSG_SET_AUTOHIDE", "$bAUTOHIDE: $b%s" },
354 { "NSMSG_SET_PASSWORD", "$bPASSWORD: $b%s" },
355 { "NSMSG_SET_FLAGS", "$bFLAGS: $b%s" },
356 { "NSMSG_SET_EMAIL", "$bEMAIL: $b%s" },
357 { "NSMSG_SET_MAXLOGINS", "$bMAXLOGINS: $b%d" },
358 { "NSMSG_SET_ADVANCED", "$bADVANCED: $b%s" },
359 { "NSMSG_SET_LANGUAGE", "$bLANGUAGE: $b%s" },
360 { "NSMSG_SET_LEVEL", "$bLEVEL: $b%d" },
361 { "NSMSG_SET_EPITHET", "$bEPITHET: $b%s" },
362 { "NSMSG_SET_NOTE", "$bNOTE: $b%s"},
363 { "NSMSG_SET_TITLE", "$bTITLE: $b%s" },
364 { "NSMSG_SET_FAKEHOST", "$bFAKEHOST: $b%s" },
366 { "NSMSG_AUTO_OPER", "You have been auto-opered" },
367 { "NSMSG_AUTO_OPER_ADMIN", "You have been auto-admined" },
369 { "NSEMAIL_ACTIVATION_SUBJECT", "Account verification for %s" },
370 { "NSEMAIL_ACTIVATION_BODY",
371 "This email has been sent to verify that this email address belongs to the person who tried to register an account on %1$s. Your cookie is:\n"
373 "To verify your email address and complete the account registration, log on to %1$s and type the following command:\n"
374 "/msg %3$s@%4$s COOKIE %5$s %2$s\n"
375 "This command is only used once to complete your account registration, and never again. Once you have run this command, you will need to authenticate everytime you reconnect to the network. To do this, you will have to type this command every time you reconnect:\n"
376 "/msg %3$s@%4$s AUTH %5$s your-password\n"
377 "(Please remember to fill in 'your-password' with the actual password you gave to us when you registered.)\n"
378 "OR configure Login-On-Connect (see http://www.afternet.org/login-on-connect for instructions) to connect pre-logged in every time.\n"
380 "If you did NOT request this account, you do not need to do anything.\n"
381 "Please contact the %1$s staff if you have questions, and be sure to check our website." },
382 { "NSEMAIL_ACTIVATION_BODY_WEB",
383 "This email has been sent to verify that this email address belongs to the person who tried to register an account on %1$s. Your cookie is:\n"
385 "To verify your email address and complete the account registration, visit the following URL:\n"
386 "http://www.afternet.org/index.php?option=com_registration&task=activate&username=%5$s&cookie=%2$s\n"
388 "If you did NOT request this account, you do not need to do anything.\n"
389 "Please contact the %1$s staff if you have questions, and be sure to check our website." },
390 { "NSEMAIL_PASSWORD_CHANGE_SUBJECT", "Password change verification on %s" },
391 { "NSEMAIL_PASSWORD_CHANGE_BODY",
392 "This email has been sent to verify that you wish to change the password on your account %5$s. Your cookie is %2$s.\n"
393 "To complete the password change, log on to %1$s and type the following command:\n"
394 "/msg %3$s@%4$s COOKIE %5$s %2$s\n"
395 "If you did NOT request your password to be changed, you do not need to do anything.\n"
396 "Please contact the %1$s staff if you have questions." },
397 { "NSEMAIL_PASSWORD_CHANGE_BODY_WEB",
398 "This email has been sent to verify that you wish to change the password on your account %5$s. Your cookie is %2$s.\n"
399 "To complete the password change, click the following URL:\n"
400 "http://www.afternet.org/index.php?option=com_registration&task=passcookie&username=%5$s&cookie=%2$s\n"
401 "If you did NOT request your password to be changed, you do not need to do anything.\n"
402 "Please contact the %1$s staff if you have questions." },
403 { "NSEMAIL_EMAIL_CHANGE_SUBJECT", "Email address change verification for %s" },
404 #ifdef stupid_verify_old_email
405 { "NSEMAIL_EMAIL_CHANGE_BODY_NEW", "This email has been sent to verify that your email address belongs to the same person as account %5$s on %1$s. The SECOND HALF of your cookie is %2$.*6$s.\nTo verify your address as associated with this account, log on to %1$s and type the following command:\n /msg %3$s@%4$s COOKIE %5$s ?????%2$.*6$s\n(Replace the ????? with the FIRST HALF of the cookie, as sent to your OLD email address.)\nIf you did NOT request this email address to be associated with this account, you do not need to do anything. Please contact the %1$s staff if you have questions." },
406 { "NSEMAIL_EMAIL_CHANGE_BODY_OLD", "This email has been sent to verify that you want to change your email for account %5$s on %1$s from this address to %7$s. The FIRST HALF of your cookie is %2$.*6$s\nTo verify your new address as associated with this account, log on to %1$s and type the following command:\n /msg %3$s@%4$s COOKIE %5$s %2$.*6$s?????\n(Replace the ????? with the SECOND HALF of the cookie, as sent to your NEW email address.)\nIf you did NOT request this change of email address, you do not need to do anything. Please contact the %1$s staff if you have questions." },
408 { "NSEMAIL_EMAIL_VERIFY_SUBJECT", "Email address verification for %s" },
409 { "NSEMAIL_EMAIL_VERIFY_BODY", "This email has been sent to verify that this address belongs to the same person as %5$s on %1$s. Your cookie is %2$s.\nTo verify your address as associated with this account, log on to %1$s and type the following command:\n /msg %3$s@%4$s COOKIE %5$s %2$s\nIf you did NOT request this email address to be associated with this account, you do not need to do anything. Please contact the %1$s staff if you have questions." },
410 { "NSEMAIL_ALLOWAUTH_SUBJECT", "Authentication allowed for %s" },
411 { "NSEMAIL_ALLOWAUTH_BODY", "This email has been sent to let you authenticate (auth) to account %5$s on %1$s. Your cookie is %2$s.\nTo auth to that account, log on to %1$s and type the following command:\n /msg %3$s@%4$s COOKIE %5$s %2$s\nIf you did NOT request this authorization, you do not need to do anything. Please contact the %1$s staff if you have questions." },
412 { "NSMSG_NOT_VALID_FAKEHOST_DOT", "$b%s$b is not a valid vhost. (needs at least one dot)" },
413 { "NSMSG_NOT_VALID_FAKEHOST_AT", "$b%s$b is not a valid vhost. (it can not have a '@')" },
414 { "NSMSG_DENIED_FAKEHOST_WORD", "Access denied because there's a prohibited word in $b%s$b (%s)." },
415 { "NSMSG_NOT_VALID_FAKEHOST_LEN", "$b%s$b is not a valid vhost. (can only be 63 characters)" },
416 { "NSMSG_NOT_VALID_FAKEHOST_TLD_LEN", "$b%s$b is not a valid vhost. (TLD can only be 4 characters and less)" },
417 { "NSMSG_NOT_VALID_FAKEHOST_REGEX", "$b%s$b is not allowed by the admin, consult the valid vhost regex pattern in the config file under nickserv/valid_fakehost_regex." },
418 { "CHECKPASS_YES", "Yes." },
419 { "CHECKPASS_NO", "No." },
420 { "CHECKEMAIL_NOT_SET", "No email set." },
421 { "CHECKEMAIL_YES", "Yes." },
422 { "CHECKEMAIL_NO", "No." },
423 { "NSMSG_DEFCON_NO_NEW_NICKS", "You cannot register new %s at this time, please try again soon" },
427 static void nickserv_reclaim(struct userNode
*user
, struct nick_info
*ni
, enum reclaim_action action
);
428 static void nickserv_reclaim_p(void *data
);
429 static int nickserv_addmask(struct userNode
*user
, struct handle_info
*hi
, const char *mask
);
431 struct nickserv_config nickserv_conf
;
433 /* We have 2^32 unique account IDs to use. */
434 unsigned long int highest_id
= 0;
437 canonicalize_hostmask(char *mask
)
439 char *out
= mask
, *temp
;
440 if ((temp
= strchr(mask
, '!'))) {
442 while (*temp
) *out
++ = *temp
++;
448 static struct handle_note
*
449 nickserv_add_note(const char *setter
, time_t date
, const char *text
)
451 struct handle_note
*note
= calloc(1, sizeof(*note
) + strlen(text
));
453 strncpy(note
->setter
, setter
, sizeof(note
->setter
)-1);
455 memcpy(note
->note
, text
, strlen(text
));
459 static struct handle_info
*
460 register_handle(const char *handle
, const char *passwd
, UNUSED_ARG(unsigned long id
))
462 struct handle_info
*hi
;
464 hi
= calloc(1, sizeof(*hi
));
465 hi
->userlist_style
= nickserv_conf
.default_style
? nickserv_conf
.default_style
: HI_DEFAULT_STYLE
;
466 hi
->announcements
= '?';
467 hi
->handle
= strdup(handle
);
468 safestrncpy(hi
->passwd
, passwd
, sizeof(hi
->passwd
));
470 dict_insert(nickserv_handle_dict
, hi
->handle
, hi
);
476 register_nick(const char *nick
, struct handle_info
*owner
)
478 struct nick_info
*ni
;
479 ni
= malloc(sizeof(struct nick_info
));
480 safestrncpy(ni
->nick
, nick
, sizeof(ni
->nick
));
482 ni
->next
= owner
->nicks
;
484 dict_insert(nickserv_nick_dict
, ni
->nick
, ni
);
488 delete_nick(struct nick_info
*ni
)
490 struct nick_info
*last
, *next
;
491 struct userNode
*user
;
492 /* Check to see if we should mark a user as unregistered. */
493 if ((user
= GetUserH(ni
->nick
)) && IsReggedNick(user
)) {
494 user
->modes
&= ~FLAGS_REGNICK
;
497 /* Remove ni from the nick_info linked list. */
498 if (ni
== ni
->owner
->nicks
) {
499 ni
->owner
->nicks
= ni
->next
;
501 last
= ni
->owner
->nicks
;
507 last
->next
= next
->next
;
509 dict_remove(nickserv_nick_dict
, ni
->nick
);
512 static unreg_func_t
*unreg_func_list
;
513 static void **unreg_func_list_extra
;
514 static unsigned int unreg_func_size
= 0, unreg_func_used
= 0;
517 reg_unreg_func(unreg_func_t func
, void *extra
)
519 if (unreg_func_used
== unreg_func_size
) {
520 if (unreg_func_size
) {
521 unreg_func_size
<<= 1;
522 unreg_func_list
= realloc(unreg_func_list
, unreg_func_size
*sizeof(unreg_func_t
));
523 unreg_func_list_extra
= realloc(unreg_func_list_extra
, unreg_func_size
*sizeof(void*));
526 unreg_func_list
= malloc(unreg_func_size
*sizeof(unreg_func_t
));
527 unreg_func_list_extra
= malloc(unreg_func_size
*sizeof(void*));
530 unreg_func_list
[unreg_func_used
] = func
;
531 unreg_func_list_extra
[unreg_func_used
++] = extra
;
535 nickserv_free_cookie(void *data
)
537 struct handle_cookie
*cookie
= data
;
538 if (cookie
->hi
) cookie
->hi
->cookie
= NULL
;
539 if (cookie
->data
) free(cookie
->data
);
544 free_handle_info(void *vhi
)
546 struct handle_info
*hi
= vhi
;
548 free_string_list(hi
->masks
);
549 free_string_list(hi
->sslfps
);
550 free_string_list(hi
->ignores
);
554 delete_nick(hi
->nicks
);
560 timeq_del(hi
->cookie
->expires
, nickserv_free_cookie
, hi
->cookie
, 0);
561 nickserv_free_cookie(hi
->cookie
);
563 if (hi
->email_addr
) {
564 struct handle_info_list
*hil
= dict_find(nickserv_email_dict
, hi
->email_addr
, NULL
);
565 handle_info_list_remove(hil
, hi
);
567 dict_remove(nickserv_email_dict
, hi
->email_addr
);
572 static void set_user_handle_info(struct userNode
*user
, struct handle_info
*hi
, int stamp
);
575 nickserv_unregister_handle(struct handle_info
*hi
, struct userNode
*notify
, struct userNode
*bot
)
578 struct userNode
*uNode
;
581 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
583 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
584 if( (rc
= ldap_delete_account(hi
->handle
)) != LDAP_SUCCESS
) {
586 send_message(notify
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
588 if(rc
!= LDAP_NO_SUCH_OBJECT
)
589 return false; /* if theres noone there to delete, its kinda ok, right ?:) */
594 for (n
=0; n
<unreg_func_used
; n
++)
595 unreg_func_list
[n
](notify
, hi
, unreg_func_list_extra
[n
]);
597 if (nickserv_conf
.sync_log
) {
598 uNode
= GetUserH(hi
->users
->nick
);
602 set_user_handle_info(hi
->users
, NULL
, 0);
605 if (nickserv_conf
.disable_nicks
)
606 send_message(notify
, bot
, "NSMSG_UNREGISTER_SUCCESS", hi
->handle
);
608 send_message(notify
, bot
, "NSMSG_UNREGISTER_NICKS_SUCCESS", hi
->handle
);
611 if (nickserv_conf
.sync_log
)
612 SyncLog("UNREGISTER %s", hi
->handle
);
614 dict_remove(nickserv_handle_dict
, hi
->handle
);
619 get_handle_info(const char *handle
)
621 return dict_find(nickserv_handle_dict
, handle
, 0);
625 get_nick_info(const char *nick
)
627 return nickserv_conf
.disable_nicks
? 0 : dict_find(nickserv_nick_dict
, nick
, 0);
631 find_handle_in_channel(struct chanNode
*channel
, struct handle_info
*handle
, struct userNode
*except
)
636 for (nn
=0; nn
<channel
->members
.used
; ++nn
) {
637 mn
= channel
->members
.list
[nn
];
638 if ((mn
->user
!= except
) && (mn
->user
->handle_info
== handle
))
645 oper_has_access(struct userNode
*user
, struct userNode
*bot
, unsigned int min_level
, unsigned int quiet
) {
646 if (!user
->handle_info
) {
648 send_message(user
, bot
, "MSG_AUTHENTICATE");
652 if (!IsOper(user
) && (!IsHelping(user
) || min_level
)) {
654 send_message(user
, bot
, "NSMSG_NO_ACCESS");
658 if (HANDLE_FLAGGED(user
->handle_info
, OPER_SUSPENDED
)) {
660 send_message(user
, bot
, "MSG_OPER_SUSPENDED");
664 if (user
->handle_info
->opserv_level
< min_level
) {
666 send_message(user
, bot
, "NSMSG_NO_ACCESS");
674 is_valid_handle(const char *handle
)
676 struct userNode
*user
;
677 /* cant register a juped nick/service nick as handle, to prevent confusion */
678 user
= GetUserH(handle
);
679 if (user
&& IsLocal(user
))
681 /* check against maximum length */
682 if (strlen(handle
) > NICKSERV_HANDLE_LEN
)
684 /* for consistency, only allow account names that could be nicks */
685 if (!is_valid_nick(handle
))
687 /* disallow account names that look like bad words */
688 if (opserv_bad_channel(handle
))
690 /* test either regex or containing all valid chars */
691 if (nickserv_conf
.valid_handle_regex_set
) {
692 int err
= regexec(&nickserv_conf
.valid_handle_regex
, handle
, 0, 0, 0);
695 buff
[regerror(err
, &nickserv_conf
.valid_handle_regex
, buff
, sizeof(buff
))] = 0;
696 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
700 return !handle
[strspn(handle
, NICKSERV_VALID_CHARS
)];
705 is_registerable_nick(const char *nick
)
707 struct userNode
*user
;
708 /* cant register a juped nick/service nick as nick, to prevent confusion */
709 user
= GetUserH(nick
);
710 if (user
&& IsLocal(user
))
712 /* for consistency, only allow nicks names that could be nicks */
713 if (!is_valid_nick(nick
))
715 /* disallow nicks that look like bad words */
716 if (opserv_bad_channel(nick
))
719 if (strlen(nick
) > NICKLEN
)
721 /* test either regex or as valid handle */
722 if (nickserv_conf
.valid_nick_regex_set
) {
723 int err
= regexec(&nickserv_conf
.valid_nick_regex
, nick
, 0, 0, 0);
726 buff
[regerror(err
, &nickserv_conf
.valid_nick_regex
, buff
, sizeof(buff
))] = 0;
727 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
733 /* this has been replaced with one in tools.c
736 is_valid_email_addr(const char *email)
738 return strchr(email, '@') != NULL;
744 visible_email_addr(struct userNode
*user
, struct handle_info
*hi
)
746 if (hi
->email_addr
) {
747 if (oper_has_access(user
, nickserv
, nickserv_conf
.email_visible_level
, 1)) {
748 return hi
->email_addr
;
758 smart_get_handle_info(struct userNode
*service
, struct userNode
*user
, const char *name
)
760 struct handle_info
*hi
;
761 struct userNode
*target
;
765 if (!(hi
= get_handle_info(++name
))) {
766 send_message(user
, service
, "MSG_HANDLE_UNKNOWN", name
);
771 if (!(target
= GetUserH(name
))) {
772 send_message(user
, service
, "MSG_NICK_UNKNOWN", name
);
775 if (IsLocal(target
)) {
776 if (IsService(target
))
777 send_message(user
, service
, "NSMSG_USER_IS_SERVICE", target
->nick
);
779 send_message(user
, service
, "MSG_USER_AUTHENTICATE", target
->nick
);
782 if (!(hi
= target
->handle_info
)) {
783 send_message(user
, service
, "MSG_USER_AUTHENTICATE", target
->nick
);
791 oper_outranks(struct userNode
*user
, struct handle_info
*hi
) {
792 if (user
->handle_info
->opserv_level
> hi
->opserv_level
)
794 if (user
->handle_info
->opserv_level
== hi
->opserv_level
) {
795 if ((user
->handle_info
->opserv_level
== 1000)
796 || (user
->handle_info
== hi
)
797 || ((user
->handle_info
->opserv_level
== 0)
798 && !(HANDLE_FLAGGED(hi
, SUPPORT_HELPER
) || HANDLE_FLAGGED(hi
, NETWORK_HELPER
))
799 && HANDLE_FLAGGED(user
->handle_info
, HELPING
))) {
803 send_message(user
, nickserv
, "MSG_USER_OUTRANKED", hi
->handle
);
808 get_victim_oper(struct userNode
*user
, const char *target
)
810 struct handle_info
*hi
;
811 if (!(hi
= smart_get_handle_info(nickserv
, user
, target
)))
813 if (HANDLE_FLAGGED(user
->handle_info
, OPER_SUSPENDED
)) {
814 send_message(user
, nickserv
, "MSG_OPER_SUSPENDED");
817 return oper_outranks(user
, hi
) ? hi
: NULL
;
821 valid_user_for(struct userNode
*user
, struct handle_info
*hi
)
825 /* If no hostmasks on the account, allow it. */
826 if (!hi
->masks
->used
)
828 /* If any hostmask matches, allow it. */
829 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
830 if (user_matches_glob(user
, hi
->masks
->list
[ii
], 0, 0))
832 /* If they are allowauthed to this account, allow it (removing the aa). */
833 if (dict_find(nickserv_allow_auth_dict
, user
->nick
, NULL
) == hi
) {
834 dict_remove(nickserv_allow_auth_dict
, user
->nick
);
837 /* The user is not allowed to use this account. */
842 valid_user_sslfp(struct userNode
*user
, struct handle_info
*hi
)
846 if (!hi
->sslfps
->used
)
851 /* If any SSL fingerprint matches, allow it. */
852 for (ii
=0; ii
<hi
->sslfps
->used
; ii
++)
853 if (!irccasecmp(user
->sslfp
, hi
->sslfps
->list
[ii
]))
856 /* No valid SSL fingerprint found. */
861 is_secure_password(const char *handle
, const char *pass
, struct userNode
*user
)
864 unsigned int cnt_digits
= 0, cnt_upper
= 0, cnt_lower
= 0;
868 if (len
< nickserv_conf
.password_min_length
) {
870 send_message(user
, nickserv
, "NSMSG_PASSWORD_SHORT", nickserv_conf
.password_min_length
);
873 if (!irccasecmp(pass
, handle
)) {
875 send_message(user
, nickserv
, "NSMSG_PASSWORD_ACCOUNT");
878 dict_find(nickserv_conf
.weak_password_dict
, pass
, &p
);
881 send_message(user
, nickserv
, "NSMSG_PASSWORD_DICTIONARY");
884 for (i
=0; i
<len
; i
++) {
885 if (isdigit(pass
[i
]))
887 if (isupper(pass
[i
]))
889 if (islower(pass
[i
]))
892 if ((cnt_lower
< nickserv_conf
.password_min_lower
)
893 || (cnt_upper
< nickserv_conf
.password_min_upper
)
894 || (cnt_digits
< nickserv_conf
.password_min_digits
)) {
896 send_message(user
, nickserv
, "NSMSG_PASSWORD_READABLE", nickserv_conf
.password_min_digits
, nickserv_conf
.password_min_upper
, nickserv_conf
.password_min_lower
);
902 static auth_func_t
*auth_func_list
;
903 static void **auth_func_list_extra
;
904 static unsigned int auth_func_size
= 0, auth_func_used
= 0;
907 reg_auth_func(auth_func_t func
, void *extra
)
909 if (auth_func_used
== auth_func_size
) {
910 if (auth_func_size
) {
911 auth_func_size
<<= 1;
912 auth_func_list
= realloc(auth_func_list
, auth_func_size
*sizeof(auth_func_t
));
913 auth_func_list_extra
= realloc(auth_func_list_extra
, auth_func_size
*sizeof(void*));
916 auth_func_list
= malloc(auth_func_size
*sizeof(auth_func_t
));
917 auth_func_list_extra
= malloc(auth_func_size
*sizeof(void*));
920 auth_func_list
[auth_func_used
] = func
;
921 auth_func_list_extra
[auth_func_used
++] = extra
;
924 static handle_rename_func_t
*rf_list
;
925 static void **rf_list_extra
;
926 static unsigned int rf_list_size
, rf_list_used
;
929 reg_handle_rename_func(handle_rename_func_t func
, void *extra
)
931 if (rf_list_used
== rf_list_size
) {
934 rf_list
= realloc(rf_list
, rf_list_size
*sizeof(rf_list
[0]));
935 rf_list_extra
= realloc(rf_list_extra
, rf_list_size
*sizeof(void*));
938 rf_list
= malloc(rf_list_size
*sizeof(rf_list
[0]));
939 rf_list_extra
= malloc(rf_list_size
*sizeof(void*));
942 rf_list
[rf_list_used
] = func
;
943 rf_list_extra
[rf_list_used
++] = extra
;
947 generate_fakehost(struct handle_info
*handle
)
949 struct userNode
*target
;
950 extern const char *hidden_host_suffix
;
951 static char buffer
[HOSTLEN
+1];
955 if (!handle
->fakehost
) {
956 data
= conf_get_data("server/hidden_host_type", RECDB_QSTRING
);
961 snprintf(buffer
, sizeof(buffer
), "%s.%s", handle
->handle
, hidden_host_suffix
);
962 else if (style
== 2) {
963 /* Due to the way fakehost is coded theres no way i can
964 get the exact user, so for now ill just take the first
966 for (target
= handle
->users
; target
; target
= target
->next_authed
)
969 snprintf(buffer
, sizeof(buffer
), "%s", target
->crypthost
);
972 } else if (handle
->fakehost
[0] == '.') {
973 /* A leading dot indicates the stored value is actually a title. */
974 snprintf(buffer
, sizeof(buffer
), "%s.%s.%s", handle
->handle
, handle
->fakehost
+1, nickserv_conf
.titlehost_suffix
);
977 return handle
->fakehost
;
981 apply_fakehost(struct handle_info
*handle
)
983 struct userNode
*target
;
988 fake
= generate_fakehost(handle
);
989 for (target
= handle
->users
; target
; target
= target
->next_authed
)
990 assign_fakehost(target
, fake
, 1);
993 void send_func_list(struct userNode
*user
)
996 struct handle_info
*old_info
;
998 old_info
= user
->handle_info
;
1000 for (n
=0; n
<auth_func_used
; n
++)
1001 auth_func_list
[n
](user
, old_info
, auth_func_list_extra
[n
]);
1005 set_user_handle_info(struct userNode
*user
, struct handle_info
*hi
, int stamp
)
1008 struct handle_info
*old_info
;
1010 /* This can happen if somebody uses COOKIE while authed, or if
1011 * they re-auth to their current handle (which is silly, but users
1012 * are like that). */
1013 if (user
->handle_info
== hi
)
1016 if (user
->handle_info
) {
1017 struct userNode
*other
;
1020 userList_remove(&curr_helpers
, user
);
1022 /* remove from next_authed linked list */
1023 if (user
->handle_info
->users
== user
) {
1024 user
->handle_info
->users
= user
->next_authed
;
1025 } else if (user
->handle_info
->users
!= NULL
) {
1026 for (other
= user
->handle_info
->users
;
1027 other
->next_authed
!= user
;
1028 other
= other
->next_authed
) ;
1029 other
->next_authed
= user
->next_authed
;
1031 /* No users authed to the account - can happen if they get
1032 * killed for authing. */
1034 /* if nobody left on old handle, and they're not an oper, remove !god */
1035 if (!user
->handle_info
->users
&& !user
->handle_info
->opserv_level
)
1036 HANDLE_CLEAR_FLAG(user
->handle_info
, HELPING
);
1037 /* record them as being last seen at this time */
1038 user
->handle_info
->lastseen
= now
;
1039 /* and record their hostmask */
1040 snprintf(user
->handle_info
->last_quit_host
, sizeof(user
->handle_info
->last_quit_host
), "%s@%s", user
->ident
, user
->hostname
);
1042 old_info
= user
->handle_info
;
1043 user
->handle_info
= hi
;
1044 if (hi
&& !hi
->users
&& !hi
->opserv_level
)
1045 HANDLE_CLEAR_FLAG(hi
, HELPING
);
1047 /* Call auth handlers */
1048 if (!GetUserH(user
->nick
))
1052 struct nick_info
*ni
;
1054 HANDLE_CLEAR_FLAG(hi
, FROZEN
);
1055 if (nickserv_conf
.warn_clone_auth
) {
1056 struct userNode
*other
;
1057 for (other
= hi
->users
; other
; other
= other
->next_authed
)
1058 send_message(other
, nickserv
, "NSMSG_CLONE_AUTH", user
->nick
, user
->ident
, user
->hostname
);
1061 /* Add this auth to users list of current auths */
1062 user
->next_authed
= hi
->users
;
1065 /* Add to helpers list */
1066 if (IsHelper(user
) && !userList_contains(&curr_helpers
, user
))
1067 userList_append(&curr_helpers
, user
);
1069 /* Set the fakehost */
1070 if (hi
->fakehost
|| old_info
)
1074 #ifdef WITH_PROTOCOL_P10
1075 /* Stamp users with their account name. */
1076 char *id
= hi
->handle
;
1078 const char *id
= "???";
1080 /* Mark all the nicks registered to this
1081 * account as registered nicks
1082 * - Why not just this one? -rubin */
1083 if (!nickserv_conf
.disable_nicks
) {
1084 struct nick_info
*ni2
;
1085 for (ni2
= hi
->nicks
; ni2
; ni2
= ni2
->next
) {
1086 if (!irccasecmp(user
->nick
, ni2
->nick
)) {
1087 user
->modes
|= FLAGS_REGNICK
;
1092 /* send the account to the ircd */
1093 StampUser(user
, id
, hi
->registered
);
1096 /* Stop trying to kick this user off their nick */
1097 if ((ni
= get_nick_info(user
->nick
)) && (ni
->owner
== hi
))
1098 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
1100 /* We cannot clear the user's account ID, unfortunately. */
1101 user
->next_authed
= NULL
;
1104 /* Call auth handlers */
1105 if (GetUserH(user
->nick
)) {
1106 for (n
=0; n
<auth_func_used
; n
++) {
1107 auth_func_list
[n
](user
, old_info
, auth_func_list_extra
[n
]);
1114 static struct handle_info
*
1115 nickserv_register(struct userNode
*user
, struct userNode
*settee
, const char *handle
, const char *passwd
, int no_auth
)
1117 struct handle_info
*hi
;
1118 struct nick_info
*ni
;
1119 char crypted
[MD5_CRYPT_LENGTH
];
1121 if ((hi
= dict_find(nickserv_handle_dict
, handle
, NULL
))) {
1123 send_message(user
, nickserv
, "NSMSG_HANDLE_EXISTS", handle
);
1127 if(strlen(handle
) > 30)
1130 send_message(user
, nickserv
, "NSMSG_HANDLE_TOLONG", handle
, 30);
1134 if (!is_secure_password(handle
, passwd
, user
))
1137 cryptpass(passwd
, crypted
);
1139 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1141 rc
= ldap_do_add(handle
, (no_auth
? NULL
: crypted
), NULL
);
1142 if(LDAP_SUCCESS
!= rc
&& LDAP_ALREADY_EXISTS
!= rc
) {
1144 send_message(user
, nickserv
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
1149 hi
= register_handle(handle
, crypted
, 0);
1150 hi
->masks
= alloc_string_list(1);
1151 hi
->sslfps
= alloc_string_list(1);
1152 hi
->ignores
= alloc_string_list(1);
1154 hi
->language
= lang_C
;
1155 hi
->registered
= now
;
1157 hi
->flags
= HI_DEFAULT_FLAGS
;
1158 if (settee
&& !no_auth
)
1159 set_user_handle_info(settee
, hi
, 1);
1161 if (user
!= settee
) {
1163 send_message(user
, nickserv
, "NSMSG_OREGISTER_H_SUCCESS");
1165 else if (nickserv_conf
.disable_nicks
) {
1167 send_message(user
, nickserv
, "NSMSG_REGISTER_H_SUCCESS");
1170 else if (user
&& (ni
= dict_find(nickserv_nick_dict
, user
->nick
, NULL
))) {
1172 send_message(user
, nickserv
, "NSMSG_PARTIAL_REGISTER");
1177 if (is_registerable_nick(user
->nick
)) {
1178 register_nick(user
->nick
, hi
);
1179 send_message(user
, nickserv
, "NSMSG_REGISTER_HN_SUCCESS");
1183 if (settee
&& (user
!= settee
)) {
1185 send_message(settee
, nickserv
, "NSMSG_OREGISTER_VICTIM", user
->nick
, hi
->handle
);
1192 nickserv_bake_cookie(struct handle_cookie
*cookie
)
1194 cookie
->hi
->cookie
= cookie
;
1195 timeq_add(cookie
->expires
, nickserv_free_cookie
, cookie
);
1198 /* Contributed by the great sneep of afternet ;) */
1199 /* Since this gets used in a URL, we want to avoid stuff that confuses
1200 * email clients such as ] and ?. a-z, 0-9 only.
1202 void genpass(char *str
, int len
)
1207 for(i
= 0; i
< len
; i
++)
1211 c
= (char)((float)rand() / (float)RAND_MAX
* (float)256);
1212 } while(!((c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z') || (c
>= '0' && c
<= '9')));
1220 nickserv_make_cookie(struct userNode
*user
, struct handle_info
*hi
, enum cookie_type type
, const char *cookie_data
, int weblink
)
1222 struct handle_cookie
*cookie
;
1223 char subject
[128], body
[4096], *misc
;
1224 const char *netname
, *fmt
;
1228 send_message(user
, nickserv
, "NSMSG_COOKIE_LIVE", hi
->handle
);
1232 cookie
= calloc(1, sizeof(*cookie
));
1234 cookie
->type
= type
;
1235 cookie
->data
= cookie_data
? strdup(cookie_data
) : NULL
;
1237 cookie
->expires
= now
+ nickserv_conf
.cookie_timeout
;
1238 /* Adding dedicated password gen function for more control -Rubin */
1239 genpass(cookie
->cookie
, 10);
1241 *inttobase64(cookie->cookie, rand(), 5);
1242 *inttobase64(cookie->cookie+5, rand(), 5);
1245 netname
= nickserv_conf
.network_name
;
1248 switch (cookie
->type
) {
1250 hi
->passwd
[0] = 0; /* invalidate password */
1251 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_REGISTER");
1252 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_SUBJECT");
1253 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1256 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_BODY_WEB");
1258 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_BODY");
1260 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1263 case PASSWORD_CHANGE
:
1264 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_RESETPASS");
1265 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_SUBJECT");
1266 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1268 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_BODY_WEB");
1270 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_BODY");
1271 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1275 misc
= hi
->email_addr
;
1276 hi
->email_addr
= cookie
->data
;
1277 #ifdef stupid_verify_old_email
1279 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_EMAIL_2");
1280 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_SUBJECT");
1281 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1282 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_BODY_NEW");
1283 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
+COOKIELEN
/2, nickserv
->nick
, self
->name
, hi
->handle
, COOKIELEN
/2);
1284 mail_send(nickserv
, hi
, subject
, body
, 1);
1285 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_BODY_OLD");
1286 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
, COOKIELEN
/2, hi
->email_addr
);
1290 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_EMAIL_1");
1291 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_VERIFY_SUBJECT");
1292 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1293 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_VERIFY_BODY");
1294 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1295 mail_send(nickserv
, hi
, subject
, body
, 1);
1297 #ifdef stupid_verify_old_email
1300 hi
->email_addr
= misc
;
1303 fmt
= handle_find_message(hi
, "NSEMAIL_ALLOWAUTH_SUBJECT");
1304 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1305 fmt
= handle_find_message(hi
, "NSEMAIL_ALLOWAUTH_BODY");
1306 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1307 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_AUTH");
1310 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d in nickserv_make_cookie.", cookie
->type
);
1314 mail_send(nickserv
, hi
, subject
, body
, first_time
);
1315 nickserv_bake_cookie(cookie
);
1319 nickserv_eat_cookie(struct handle_cookie
*cookie
)
1321 cookie
->hi
->cookie
= NULL
;
1322 timeq_del(cookie
->expires
, nickserv_free_cookie
, cookie
, 0);
1323 nickserv_free_cookie(cookie
);
1327 nickserv_free_email_addr(void *data
)
1329 handle_info_list_clean(data
);
1334 nickserv_set_email_addr(struct handle_info
*hi
, const char *new_email_addr
)
1336 struct handle_info_list
*hil
;
1337 /* Remove from old handle_info_list ... */
1338 if (hi
->email_addr
&& (hil
= dict_find(nickserv_email_dict
, hi
->email_addr
, 0))) {
1339 handle_info_list_remove(hil
, hi
);
1340 if (!hil
->used
) dict_remove(nickserv_email_dict
, hil
->tag
);
1341 hi
->email_addr
= NULL
;
1343 /* Add to the new list.. */
1344 if (new_email_addr
) {
1345 if (!(hil
= dict_find(nickserv_email_dict
, new_email_addr
, 0))) {
1346 hil
= calloc(1, sizeof(*hil
));
1347 hil
->tag
= strdup(new_email_addr
);
1348 handle_info_list_init(hil
);
1349 dict_insert(nickserv_email_dict
, hil
->tag
, hil
);
1351 handle_info_list_append(hil
, hi
);
1352 hi
->email_addr
= hil
->tag
;
1356 static NICKSERV_FUNC(cmd_register
)
1359 struct handle_info
*hi
;
1360 const char *email_addr
, *password
;
1361 char syncpass
[MD5_CRYPT_LENGTH
];
1362 int no_auth
, weblink
;
1364 if (checkDefCon(DEFCON_NO_NEW_NICKS
) && !IsOper(user
)) {
1365 reply("NSMSG_DEFCON_NO_NEW_NICKS", nickserv_conf
.disable_nicks
? "accounts" : "nicknames");
1369 if (!IsOper(user
) && !dict_size(nickserv_handle_dict
)) {
1370 /* Require the first handle registered to belong to someone +o. */
1371 reply("NSMSG_REQUIRE_OPER");
1375 if (user
->handle_info
) {
1376 reply("NSMSG_USE_RENAME", user
->handle_info
->handle
);
1380 if (IsRegistering(user
)) {
1381 reply("NSMSG_ALREADY_REGISTERING");
1385 if (IsStamped(user
)) {
1386 /* Unauthenticated users might still have been stamped
1387 previously and could therefore have a hidden host;
1388 do not allow them to register a new account. */
1389 reply("NSMSG_STAMPED_REGISTER");
1393 NICKSERV_MIN_PARMS((unsigned)3 + nickserv_conf
.email_required
);
1395 if(nickserv_conf
.force_handles_lowercase
)
1396 irc_strtolower(argv
[1]);
1397 if (!is_valid_handle(argv
[1])) {
1398 reply("NSMSG_BAD_HANDLE", argv
[1]);
1403 if ((argc
>= 4) && nickserv_conf
.email_enabled
) {
1404 struct handle_info_list
*hil
;
1407 /* Remember email address. */
1408 email_addr
= argv
[3];
1410 /* Check that the email address looks valid.. */
1411 if (!valid_email(email_addr
)) {
1412 reply("NSMSG_BAD_EMAIL_ADDR");
1416 /* .. and that we are allowed to send to it. */
1417 if ((str
= mail_prohibited_address(email_addr
))) {
1418 reply("NSMSG_EMAIL_PROHIBITED", email_addr
, str
);
1422 /* If we do email verify, make sure we don't spam the address. */
1423 if ((hil
= dict_find(nickserv_email_dict
, email_addr
, NULL
))) {
1425 for (nn
=0; nn
<hil
->used
; nn
++) {
1426 if (hil
->list
[nn
]->cookie
) {
1427 reply("NSMSG_EMAIL_UNACTIVATED");
1431 if (hil
->used
>= nickserv_conf
.handles_per_email
) {
1432 reply("NSMSG_EMAIL_OVERUSED");
1445 /* Webregister hack - send URL instead of IRC cookie
1448 if((argc
>= 5) && !strcmp(argv
[4],"WEBLINK"))
1452 if (!(hi
= nickserv_register(user
, user
, argv
[1], password
, no_auth
)))
1454 /* Add any masks they should get. */
1455 if (nickserv_conf
.default_hostmask
) {
1456 string_list_append(hi
->masks
, strdup("*@*"));
1458 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
1459 if (irc_in_addr_is_valid(user
->ip
) && !irc_pton(&ip
, NULL
, user
->hostname
))
1460 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_BYIP
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
1463 /* If they're the first to register, give them level 1000. */
1464 if (dict_size(nickserv_handle_dict
) == 1) {
1465 hi
->opserv_level
= 1000;
1466 reply("NSMSG_ROOT_HANDLE", argv
[1]);
1469 /* Set their email address. */
1472 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1474 if((rc
= ldap_do_modify(hi
->handle
, NULL
, email_addr
)) != LDAP_SUCCESS
) {
1475 /* Falied to update email in ldap, but still
1476 * updated it here.. what should we do? */
1477 reply("NSMSG_LDAP_FAIL_EMAIL", ldap_err2string(rc
));
1479 nickserv_set_email_addr(hi
, email_addr
);
1483 nickserv_set_email_addr(hi
, email_addr
);
1486 nickserv_set_email_addr(hi
, email_addr
);
1490 /* If they need to do email verification, tell them. */
1492 nickserv_make_cookie(user
, hi
, ACTIVATION
, hi
->passwd
, weblink
);
1494 /* Set registering flag.. */
1495 user
->modes
|= FLAGS_REGISTERING
;
1497 if (nickserv_conf
.sync_log
) {
1498 cryptpass(password
, syncpass
);
1500 * An 0 is only sent if theres no email address. Thios should only happen if email functions are
1501 * disabled which they wont be for us. Email Required MUST be set on if you are using this.
1504 SyncLog("REGISTER %s %s %s %s", hi
->handle
, syncpass
, email_addr
? email_addr
: "0", user
->info
);
1507 /* this wont work if email is required .. */
1508 process_adduser_pending(user
);
1513 static NICKSERV_FUNC(cmd_oregister
)
1515 struct userNode
*settee
= NULL
;
1516 struct handle_info
*hi
;
1517 char* account
= NULL
;
1523 NICKSERV_MIN_PARMS(2);
1527 if(nickserv_conf
.force_handles_lowercase
)
1528 irc_strtolower(account
);
1529 if (!is_valid_handle(argv
[1])) {
1530 reply("NSMSG_BAD_HANDLE", argv
[1]);
1533 if (nickserv_conf
.email_required
) {
1534 NICKSERV_MIN_PARMS(3);
1536 if (argc
> 4) {/* take: "acct pass email mask nick" or "acct pass email mask" or "acct pass email nick" */
1537 if (strchr(argv
[4], '@'))
1547 if (argc
> 3) {/* take: "account pass mask nick" or "account pass mask" or "account pass nick" */
1548 if (strchr(argv
[3], '@'))
1557 /* If they passed a nick, look for that user.. */
1558 if (nick
&& !(settee
= GetUserH(nick
))) {
1559 reply("MSG_NICK_UNKNOWN", argv
[4]);
1562 /* If the setee is already authed, we cant add a 2nd account for them.. */
1563 if (settee
&& settee
->handle_info
) {
1564 reply("NSMSG_USER_PREV_AUTH", settee
->nick
);
1567 /* If there is no default mask in the conf, and they didn't pass a mask,
1568 * but we did find a user by nick, generate the mask */
1570 if (nickserv_conf
.default_hostmask
)
1573 mask
= generate_hostmask(settee
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
1575 reply("NSMSG_REGISTER_BAD_NICKMASK");
1580 if (!(hi
= nickserv_register(user
, settee
, account
, pass
, 0))) {
1581 return 0; /* error reply handled by above */
1585 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1587 if((rc
= ldap_do_modify(hi
->handle
, NULL
, email
)) != LDAP_SUCCESS
) {
1588 /* Falied to update email in ldap, but still
1589 * updated it here.. what should we do? */
1590 reply("NSMSG_LDAP_FAIL_EMAIL", ldap_err2string(rc
));
1592 nickserv_set_email_addr(hi
, email
);
1596 nickserv_set_email_addr(hi
, email
);
1599 nickserv_set_email_addr(hi
, email
);
1603 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
1604 if (mask_canonicalized
)
1605 string_list_append(hi
->masks
, mask_canonicalized
);
1608 if (nickserv_conf
.sync_log
)
1609 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, email
? email
: "@", user
->info
); /* Send just @ for email if none */
1614 nickserv_ignore(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, char *mask
)
1617 struct userNode
*target
;
1618 char *new_mask
= strdup(pretty_mask(mask
));
1619 for (i
=0; i
<hi
->ignores
->used
; i
++) {
1620 if (!irccasecmp(new_mask
, hi
->ignores
->list
[i
])) {
1621 reply("NSMSG_ADDIGNORE_ALREADY", new_mask
);
1626 string_list_append(hi
->ignores
, new_mask
);
1627 reply("NSMSG_ADDIGNORE_SUCCESS", new_mask
);
1629 for (target
= hi
->users
; target
; target
= target
->next_authed
) {
1630 irc_silence(target
, new_mask
, 1);
1635 static NICKSERV_FUNC(cmd_addignore
)
1637 NICKSERV_MIN_PARMS(2);
1639 return nickserv_ignore(cmd
, user
, user
->handle_info
, argv
[1]);
1642 static NICKSERV_FUNC(cmd_oaddignore
)
1644 struct handle_info
*hi
;
1646 NICKSERV_MIN_PARMS(3);
1647 if (!(hi
= get_victim_oper(user
, argv
[1])))
1650 return nickserv_ignore(cmd
, user
, hi
, argv
[2]);
1654 nickserv_delignore(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, char *del_mask
)
1657 struct userNode
*target
;
1658 char *pmask
= strdup(pretty_mask(del_mask
));
1659 for (i
=0; i
<hi
->ignores
->used
; i
++) {
1660 if (!strcmp(pmask
, hi
->ignores
->list
[i
]) || !strcmp(del_mask
, hi
->ignores
->list
[i
])) {
1661 char *old_mask
= hi
->ignores
->list
[i
];
1662 hi
->ignores
->list
[i
] = hi
->ignores
->list
[--hi
->ignores
->used
];
1663 reply("NSMSG_DELMASK_SUCCESS", old_mask
);
1664 for (target
= hi
->users
; target
; target
= target
->next_authed
) {
1665 irc_silence(target
, old_mask
, 0);
1672 reply("NSMSG_DELMASK_NOT_FOUND");
1676 static NICKSERV_FUNC(cmd_delignore
)
1678 NICKSERV_MIN_PARMS(2);
1679 return nickserv_delignore(cmd
, user
, user
->handle_info
, argv
[1]);
1682 static NICKSERV_FUNC(cmd_odelignore
)
1684 struct handle_info
*hi
;
1685 NICKSERV_MIN_PARMS(3);
1686 if (!(hi
= get_victim_oper(user
, argv
[1])))
1688 return nickserv_delignore(cmd
, user
, hi
, argv
[2]);
1691 static NICKSERV_FUNC(cmd_handleinfo
)
1694 unsigned int i
, pos
=0, herelen
;
1695 struct userNode
*target
, *next_un
;
1696 struct handle_info
*hi
;
1697 const char *nsmsg_none
;
1700 if (!(hi
= user
->handle_info
)) {
1701 reply("NSMSG_MUST_AUTH");
1704 } else if (!(hi
= modcmd_get_handle_info(user
, argv
[1]))) {
1708 nsmsg_none
= handle_find_message(hi
, "MSG_NONE");
1709 reply("NSMSG_HANDLEINFO_ON", hi
->handle
);
1711 reply("NSMSG_HANDLEINFO_REGGED", ctime(&hi
->registered
));
1714 intervalString(buff
, now
- hi
->lastseen
, user
->handle_info
);
1715 reply("NSMSG_HANDLEINFO_LASTSEEN", buff
);
1717 reply("NSMSG_HANDLEINFO_LASTSEEN_NOW");
1720 reply("NSMSG_HANDLEINFO_INFOLINE", (hi
->infoline
? hi
->infoline
: nsmsg_none
));
1721 if (HANDLE_FLAGGED(hi
, FROZEN
))
1722 reply("NSMSG_HANDLEINFO_VACATION");
1724 if (oper_has_access(user
, cmd
->parent
->bot
, 0, 1)) {
1725 struct do_not_register
*dnr
;
1726 if ((dnr
= chanserv_is_dnr(NULL
, hi
)))
1727 reply("NSMSG_HANDLEINFO_DNR", dnr
->setter
, dnr
->reason
);
1728 if ((user
->handle_info
->opserv_level
< 900) && !oper_outranks(user
, hi
))
1730 } else if (hi
!= user
->handle_info
) {
1731 reply("NSMSG_HANDLEINFO_END");
1736 reply("NSMSG_HANDLEINFO_KARMA", hi
->karma
);
1738 if (nickserv_conf
.email_enabled
)
1739 reply("NSMSG_HANDLEINFO_EMAIL_ADDR", visible_email_addr(user
, hi
));
1743 switch (hi
->cookie
->type
) {
1744 case ACTIVATION
: type
= "NSMSG_HANDLEINFO_COOKIE_ACTIVATION"; break;
1745 case PASSWORD_CHANGE
: type
= "NSMSG_HANDLEINFO_COOKIE_PASSWORD"; break;
1746 case EMAIL_CHANGE
: type
= "NSMSG_HANDLEINFO_COOKIE_EMAIL"; break;
1747 case ALLOWAUTH
: type
= "NSMSG_HANDLEINFO_COOKIE_ALLOWAUTH"; break;
1748 default: type
= "NSMSG_HANDLEINFO_COOKIE_UNKNOWN"; break;
1754 unsigned long flen
= 1;
1755 char flags
[34]; /* 32 bits possible plus '+' and '\0' */
1757 for (i
=0, flen
=1; handle_flags
[i
]; i
++)
1758 if (hi
->flags
& 1 << i
)
1759 flags
[flen
++] = handle_flags
[i
];
1761 reply("NSMSG_HANDLEINFO_FLAGS", flags
);
1763 reply("NSMSG_HANDLEINFO_FLAGS", nsmsg_none
);
1766 if (HANDLE_FLAGGED(hi
, SUPPORT_HELPER
)
1767 || HANDLE_FLAGGED(hi
, NETWORK_HELPER
)
1768 || (hi
->opserv_level
> 0)) {
1769 reply("NSMSG_HANDLEINFO_EPITHET", (hi
->epithet
? hi
->epithet
: nsmsg_none
));
1772 if (IsHelping(user
) || IsOper(user
))
1777 strftime(date
, 64, "%b %d %Y", localtime(&hi
->note
->date
));
1778 reply("NSMSG_HANDLEINFO_NOTE", hi
->note
->setter
, date
, hi
->note
->note
);
1783 reply("NSMSG_HANDLEINFO_FAKEHOST", (hi
->fakehost
? hi
->fakehost
: handle_find_message(hi
, "MSG_NONE")));
1785 if (hi
->last_quit_host
[0])
1786 reply("NSMSG_HANDLEINFO_LAST_HOST", hi
->last_quit_host
);
1788 reply("NSMSG_HANDLEINFO_LAST_HOST_UNKNOWN");
1790 if (nickserv_conf
.disable_nicks
) {
1791 /* nicks disabled; don't show anything about registered nicks */
1792 } else if (hi
->nicks
) {
1793 struct nick_info
*ni
, *next_ni
;
1794 for (ni
= hi
->nicks
; ni
; ni
= next_ni
) {
1795 herelen
= strlen(ni
->nick
);
1796 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1798 goto print_nicks_buff
;
1802 memcpy(buff
+pos
, ni
->nick
, herelen
);
1803 pos
+= herelen
; buff
[pos
++] = ' ';
1807 reply("NSMSG_HANDLEINFO_NICKS", buff
);
1812 reply("NSMSG_HANDLEINFO_NICKS", nsmsg_none
);
1815 if (hi
->masks
->used
) {
1816 for (i
=0; i
< hi
->masks
->used
; i
++) {
1817 herelen
= strlen(hi
->masks
->list
[i
]);
1818 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1820 goto print_mask_buff
;
1822 memcpy(buff
+pos
, hi
->masks
->list
[i
], herelen
);
1823 pos
+= herelen
; buff
[pos
++] = ' ';
1824 if (i
+1 == hi
->masks
->used
) {
1827 reply("NSMSG_HANDLEINFO_MASKS", buff
);
1832 reply("NSMSG_HANDLEINFO_MASKS", nsmsg_none
);
1835 if (hi
->sslfps
->used
) {
1836 for (i
=0; i
< hi
->sslfps
->used
; i
++) {
1837 herelen
= strlen(hi
->sslfps
->list
[i
]);
1838 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1840 goto print_sslfp_buff
;
1842 memcpy(buff
+pos
, hi
->sslfps
->list
[i
], herelen
);
1843 pos
+= herelen
; buff
[pos
++] = ' ';
1844 if (i
+1 == hi
->sslfps
->used
) {
1847 reply("NSMSG_HANDLEINFO_SSLFPS", buff
);
1852 reply("NSMSG_HANDLEINFO_SSLFPS", nsmsg_none
);
1855 if (hi
->ignores
->used
) {
1856 for (i
=0; i
< hi
->ignores
->used
; i
++) {
1857 herelen
= strlen(hi
->ignores
->list
[i
]);
1858 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1860 goto print_ignore_buff
;
1862 memcpy(buff
+pos
, hi
->ignores
->list
[i
], herelen
);
1863 pos
+= herelen
; buff
[pos
++] = ' ';
1864 if (i
+1 == hi
->ignores
->used
) {
1867 reply("NSMSG_HANDLEINFO_IGNORES", buff
);
1872 reply("NSMSG_HANDLEINFO_IGNORES", nsmsg_none
);
1876 struct userData
*chan
, *next
;
1879 for (chan
= hi
->channels
; chan
; chan
= next
) {
1880 next
= chan
->u_next
;
1881 name
= chan
->channel
->channel
->name
;
1882 herelen
= strlen(name
);
1883 if (pos
+ herelen
+ 7 > ArrayLength(buff
)) {
1885 goto print_chans_buff
;
1887 if (IsUserSuspended(chan
))
1889 pos
+= sprintf(buff
+pos
, "%s:%s ", user_level_name_from_level(chan
->access
), name
);
1893 reply("NSMSG_HANDLEINFO_CHANNELS", buff
);
1898 reply("NSMSG_HANDLEINFO_CHANNELS", nsmsg_none
);
1901 for (target
= hi
->users
; target
; target
= next_un
) {
1902 herelen
= strlen(target
->nick
);
1903 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1905 goto print_cnick_buff
;
1907 next_un
= target
->next_authed
;
1909 memcpy(buff
+pos
, target
->nick
, herelen
);
1910 pos
+= herelen
; buff
[pos
++] = ' ';
1914 reply("NSMSG_HANDLEINFO_CURRENT", buff
);
1919 reply("NSMSG_HANDLEINFO_END");
1920 return 1 | ((hi
!= user
->handle_info
) ? CMD_LOG_STAFF
: 0);
1923 static NICKSERV_FUNC(cmd_userinfo
)
1925 struct userNode
*target
;
1927 NICKSERV_MIN_PARMS(2);
1928 if (!(target
= GetUserH(argv
[1]))) {
1929 reply("MSG_NICK_UNKNOWN", argv
[1]);
1932 if (target
->handle_info
)
1933 reply("NSMSG_USERINFO_AUTHED_AS", target
->nick
, target
->handle_info
->handle
);
1935 reply("NSMSG_USERINFO_NOT_AUTHED", target
->nick
);
1939 static NICKSERV_FUNC(cmd_nickinfo
)
1941 struct nick_info
*ni
;
1943 NICKSERV_MIN_PARMS(2);
1944 if (!(ni
= get_nick_info(argv
[1]))) {
1945 reply("MSG_NICK_UNKNOWN", argv
[1]);
1948 reply("NSMSG_NICKINFO_OWNER", ni
->nick
, ni
->owner
->handle
);
1952 static NICKSERV_FUNC(cmd_rename_handle
)
1954 struct handle_info
*hi
;
1955 struct userNode
*uNode
;
1959 NICKSERV_MIN_PARMS(3);
1960 if(nickserv_conf
.force_handles_lowercase
)
1961 irc_strtolower(argv
[2]);
1962 if (!(hi
= get_victim_oper(user
, argv
[1])))
1964 if (!is_valid_handle(argv
[2])) {
1965 reply("NSMSG_FAIL_RENAME", argv
[1], argv
[2]);
1968 if (get_handle_info(argv
[2])) {
1969 reply("NSMSG_HANDLE_EXISTS", argv
[2]);
1972 if(strlen(argv
[2]) > 30)
1974 reply("NMSG_HANDLE_TOLONG", argv
[2], 30);
1978 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1980 if( (rc
= ldap_rename_account(hi
->handle
, argv
[2])) != LDAP_SUCCESS
) {
1981 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
1987 dict_remove2(nickserv_handle_dict
, old_handle
= hi
->handle
, 1);
1988 hi
->handle
= strdup(argv
[2]);
1989 dict_insert(nickserv_handle_dict
, hi
->handle
, hi
);
1990 for (nn
=0; nn
<rf_list_used
; nn
++)
1991 rf_list
[nn
](hi
, old_handle
, rf_list_extra
[nn
]);
1993 if (nickserv_conf
.sync_log
) {
1994 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
1995 irc_rename(uNode
, hi
->handle
);
1997 SyncLog("RENAME %s %s", old_handle
, hi
->handle
);
2000 reply("NSMSG_HANDLE_CHANGED", old_handle
, hi
->handle
);
2001 global_message_args(MESSAGE_RECIPIENT_OPERS
, "NSMSG_ACCOUNT_RENAMED",
2002 user
->handle_info
->handle
, old_handle
, hi
->handle
);
2008 static failpw_func_t
*failpw_func_list
;
2009 static void **failpw_func_list_extra
;
2010 static unsigned int failpw_func_size
= 0, failpw_func_used
= 0;
2013 reg_failpw_func(failpw_func_t func
, void *extra
)
2015 if (failpw_func_used
== failpw_func_size
) {
2016 if (failpw_func_size
) {
2017 failpw_func_size
<<= 1;
2018 failpw_func_list
= realloc(failpw_func_list
, failpw_func_size
*sizeof(failpw_func_t
));
2019 failpw_func_list_extra
= realloc(failpw_func_list_extra
, failpw_func_size
*sizeof(void*));
2021 failpw_func_size
= 8;
2022 failpw_func_list
= malloc(failpw_func_size
*sizeof(failpw_func_t
));
2023 failpw_func_list_extra
= malloc(failpw_func_size
*sizeof(void*));
2026 failpw_func_list
[failpw_func_used
] = func
;
2027 failpw_func_list_extra
[failpw_func_used
++] = extra
;
2031 * Return hi if the handle/pass pair matches, NULL if it doesnt.
2033 * called by nefariouses enhanced AC login-on-connect code
2036 struct handle_info
*loc_auth(char *sslfp
, char *handle
, char *password
, char *userhost
)
2038 int wildmask
= 0, auth
= 0;
2039 int used
, maxlogins
;
2041 struct handle_info
*hi
;
2042 struct userNode
*other
;
2044 int ldap_result
= LDAP_SUCCESS
;
2048 hi
= dict_find(nickserv_handle_dict
, handle
, NULL
);
2051 if (nickserv_conf
.ldap_enable
) {
2052 ldap_result
= ldap_check_auth(handle
, password
);
2053 if (!hi
&& (ldap_result
!= LDAP_SUCCESS
))
2055 if (ldap_result
== LDAP_SUCCESS
) {
2056 /* Mark auth as successful */
2060 if (!hi
&& (ldap_result
== LDAP_SUCCESS
) && nickserv_conf
.ldap_autocreate
) {
2061 /* user not found, but authed to ldap successfully..
2062 * create the account.
2067 /* Add a *@* mask */
2068 /* TODO if userhost is not null, build mask based on that. */
2069 if(nickserv_conf
.default_hostmask
)
2072 return NULL
; /* They dont have a *@* mask so they can't loc */
2074 if(!(hi
= nickserv_register(NULL
, NULL
, handle
, password
, 0))) {
2075 return 0; /* couldn't add the user for some reason */
2078 if((rc
= ldap_get_user_info(handle
, &email
) != LDAP_SUCCESS
))
2080 if(nickserv_conf
.email_required
) {
2085 nickserv_set_email_addr(hi
, email
);
2089 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
2090 string_list_append(hi
->masks
, mask_canonicalized
);
2092 if(nickserv_conf
.sync_log
)
2093 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, "@", handle
);
2098 /* hi should now be a valid handle, if not return NULL */
2103 if (password
&& *password
&& !nickserv_conf
.ldap_enable
) {
2105 if (password
&& *password
) {
2107 if (checkpass(password
, hi
->passwd
))
2111 if (!auth
&& sslfp
&& *sslfp
&& hi
->sslfps
->used
) {
2112 /* If any SSL fingerprint matches, allow it. */
2113 for (ii
=0; ii
<hi
->sslfps
->used
; ii
++) {
2114 if (!irccasecmp(sslfp
, hi
->sslfps
->list
[ii
])) {
2121 /* Auth should have succeeded by this point */
2125 /* We don't know the users hostname, or anything because they
2126 * havn't registered yet. So we can only allow LOC if your
2127 * account has *@* as a hostmask.
2129 * UPDATE: New nefarious LOC supports u@h
2139 buf
= strdup(userhost
);
2140 ident
= mysep(&buf
, "@");
2141 realhost
= mysep(&buf
, ":");
2142 ip
= mysep(&buf
, ":");
2143 if(!ip
|| !realhost
|| !ident
) {
2145 return NULL
; /* Invalid AC request, just quit */
2147 uh
= malloc(strlen(userhost
));
2148 ui
= malloc(strlen(userhost
));
2149 sprintf(uh
, "%s@%s", ident
, realhost
);
2150 sprintf(ui
, "%s@%s", ident
, ip
);
2151 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
2153 if(match_ircglob(uh
, hi
->masks
->list
[ii
])
2154 || match_ircglob(ui
, hi
->masks
->list
[ii
]))
2166 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
2168 if (!strcmp(hi
->masks
->list
[ii
], "*@*"))
2178 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2182 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
2183 for (used
= 0, other
= hi
->users
; other
; other
= other
->next_authed
) {
2184 if (++used
>= maxlogins
) {
2188 /* TODO - Add LOGGING to this function so LOC's are logged.. */
2192 static NICKSERV_FUNC(cmd_auth
)
2194 int pw_arg
, used
, maxlogins
;
2195 struct handle_info
*hi
;
2198 struct userNode
*other
;
2200 int ldap_result
= LDAP_OTHER
;
2204 if (user
->handle_info
) {
2205 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2208 if (IsStamped(user
)) {
2209 /* Unauthenticated users might still have been stamped
2210 previously and could therefore have a hidden host;
2211 do not allow them to authenticate. */
2212 reply("NSMSG_STAMPED_AUTH");
2219 hi
= dict_find(nickserv_handle_dict
, argv
[1], NULL
);
2220 } else if (argc
== 2) {
2223 if (nickserv_conf
.disable_nicks
) {
2224 hi
= get_handle_info(user
->nick
);
2226 /* try to look up their handle from their nick */
2227 /* TODO: handle ldap auth on nickserv style networks, too */
2228 struct nick_info
*ni
;
2229 ni
= get_nick_info(user
->nick
);
2231 reply("NSMSG_NICK_NOT_REGISTERED", user
->nick
);
2237 handle
= hi
->handle
;
2239 handle
= user
->nick
;
2242 reply("MSG_MISSING_PARAMS", argv
[0]);
2243 svccmd_send_help_brief(user
, nickserv
, cmd
);
2248 if(strchr(argv
[1], '<') || strchr(handle
, '>')) {
2249 reply("NSMSG_NO_ANGLEBRACKETS");
2252 if (!is_valid_handle(handle
)) {
2253 reply("NSMSG_BAD_HANDLE", handle
);
2257 if(nickserv_conf
.ldap_enable
) {
2258 ldap_result
= ldap_check_auth(handle
, passwd
);
2259 /* Get the users email address and update it */
2260 if(ldap_result
== LDAP_SUCCESS
) {
2262 if((rc
= ldap_get_user_info(handle
, &email
) != LDAP_SUCCESS
))
2264 if(nickserv_conf
.email_required
) {
2265 reply("NSMSG_LDAP_FAIL_GET_EMAIL", ldap_err2string(rc
));
2270 else if(ldap_result
!= LDAP_INVALID_CREDENTIALS
) {
2271 reply("NSMSG_LDAP_FAIL", ldap_err2string(ldap_result
));
2279 if(nickserv_conf
.ldap_enable
&& ldap_result
== LDAP_SUCCESS
&& nickserv_conf
.ldap_autocreate
) {
2280 /* user not found, but authed to ldap successfully..
2281 * create the account.
2284 if(!(hi
= nickserv_register(user
, NULL
, argv
[1], argv
[2], 0))) {
2285 reply("NSMSG_UNABLE_TO_ADD");
2286 return 0; /* couldn't add the user for some reason */
2288 /* Add a *@* mask */
2289 if(nickserv_conf
.default_hostmask
)
2292 mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2295 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
2296 string_list_append(hi
->masks
, mask_canonicalized
);
2299 nickserv_set_email_addr(hi
, email
);
2302 if(nickserv_conf
.sync_log
)
2303 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, email
? email
: "@", user
->info
);
2307 reply("NSMSG_HANDLE_NOT_FOUND");
2313 /* Responses from here on look up the language used by the handle they asked about. */
2314 if (!valid_user_for(user
, hi
)) {
2315 if (hi
->email_addr
&& nickserv_conf
.email_enabled
)
2316 send_message_type(4, user
, cmd
->parent
->bot
,
2317 handle_find_message(hi
, "NSMSG_USE_AUTHCOOKIE"),
2320 send_message_type(4, user
, cmd
->parent
->bot
,
2321 handle_find_message(hi
, "NSMSG_HOSTMASK_INVALID"),
2323 argv
[pw_arg
] = "BADMASK";
2327 if(( ( nickserv_conf
.ldap_enable
&& ldap_result
== LDAP_INVALID_CREDENTIALS
) ||
2328 ( (!nickserv_conf
.ldap_enable
) && (!checkpass(passwd
, hi
->passwd
)) ) ) && !valid_user_sslfp(user
, hi
)) {
2330 if (!checkpass(passwd
, hi
->passwd
) && !valid_user_sslfp(user
, hi
)) {
2333 send_message_type(4, user
, cmd
->parent
->bot
,
2334 handle_find_message(hi
, "NSMSG_PASSWORD_INVALID"));
2335 argv
[pw_arg
] = "BADPASS";
2336 for (n
=0; n
<failpw_func_used
; n
++)
2337 failpw_func_list
[n
](user
, hi
, failpw_func_list_extra
[n
]);
2338 if (nickserv_conf
.autogag_enabled
) {
2339 if (!user
->auth_policer
.params
) {
2340 user
->auth_policer
.last_req
= now
;
2341 user
->auth_policer
.params
= nickserv_conf
.auth_policer_params
;
2343 if (!policer_conforms(&user
->auth_policer
, now
, 1.0)) {
2345 hostmask
= generate_hostmask(user
, GENMASK_STRICT_HOST
|GENMASK_BYIP
|GENMASK_NO_HIDING
);
2346 log_module(NS_LOG
, LOG_INFO
, "%s auto-gagged for repeated password guessing.", hostmask
);
2347 gag_create(hostmask
, nickserv
->nick
, "Repeated password guessing.", now
+nickserv_conf
.autogag_duration
);
2349 argv
[pw_arg
] = "GAGGED";
2354 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2355 send_message_type(4, user
, cmd
->parent
->bot
,
2356 handle_find_message(hi
, "NSMSG_HANDLE_SUSPENDED"));
2357 argv
[pw_arg
] = "SUSPENDED";
2360 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
2361 for (used
= 0, other
= hi
->users
; other
; other
= other
->next_authed
) {
2362 if (++used
>= maxlogins
) {
2363 send_message_type(4, user
, cmd
->parent
->bot
,
2364 handle_find_message(hi
, "NSMSG_MAX_LOGINS"),
2366 argv
[pw_arg
] = "MAXLOGINS";
2371 set_user_handle_info(user
, hi
, 1);
2372 if (nickserv_conf
.email_required
&& !hi
->email_addr
)
2373 reply("NSMSG_PLEASE_SET_EMAIL");
2374 if (!is_secure_password(hi
->handle
, passwd
, NULL
))
2375 reply("NSMSG_WEAK_PASSWORD");
2376 if (hi
->passwd
[0] != '$')
2377 cryptpass(passwd
, hi
->passwd
);
2379 /* If a channel was waiting for this user to auth,
2380 * finish adding them */
2381 process_adduser_pending(user
);
2383 reply("NSMSG_AUTH_SUCCESS");
2386 /* Set +x if autohide is on */
2387 if(HANDLE_FLAGGED(hi
, AUTOHIDE
))
2388 irc_umode(user
, "+x");
2390 if (!hi
->masks
->used
) {
2392 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
2393 if (irc_in_addr_is_valid(user
->ip
) && irc_pton(&ip
, NULL
, user
->hostname
))
2394 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_BYIP
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
2397 /* Wipe out the pass for the logs */
2398 argv
[pw_arg
] = "****";
2402 static allowauth_func_t
*allowauth_func_list
;
2403 static void **allowauth_func_list_extra
;
2404 static unsigned int allowauth_func_size
= 0, allowauth_func_used
= 0;
2407 reg_allowauth_func(allowauth_func_t func
, void *extra
)
2409 if (allowauth_func_used
== allowauth_func_size
) {
2410 if (allowauth_func_size
) {
2411 allowauth_func_size
<<= 1;
2412 allowauth_func_list
= realloc(allowauth_func_list
, allowauth_func_size
*sizeof(allowauth_func_t
));
2413 allowauth_func_list_extra
= realloc(allowauth_func_list_extra
, allowauth_func_size
*sizeof(void*));
2415 allowauth_func_size
= 8;
2416 allowauth_func_list
= malloc(allowauth_func_size
*sizeof(allowauth_func_t
));
2417 allowauth_func_list_extra
= malloc(allowauth_func_size
*sizeof(void*));
2420 allowauth_func_list
[allowauth_func_used
] = func
;
2421 allowauth_func_list_extra
[allowauth_func_used
++] = extra
;
2424 static NICKSERV_FUNC(cmd_allowauth
)
2426 struct userNode
*target
;
2427 struct handle_info
*hi
;
2430 NICKSERV_MIN_PARMS(2);
2431 if (!(target
= GetUserH(argv
[1]))) {
2432 reply("MSG_NICK_UNKNOWN", argv
[1]);
2435 if (target
->handle_info
) {
2436 reply("NSMSG_USER_PREV_AUTH", target
->nick
);
2439 if (IsStamped(target
)) {
2440 /* Unauthenticated users might still have been stamped
2441 previously and could therefore have a hidden host;
2442 do not allow them to authenticate to an account. */
2443 reply("NSMSG_USER_PREV_STAMP", target
->nick
);
2448 else if (!(hi
= get_handle_info(argv
[2]))) {
2449 reply("MSG_HANDLE_UNKNOWN", argv
[2]);
2453 if (hi
->opserv_level
> user
->handle_info
->opserv_level
) {
2454 reply("MSG_USER_OUTRANKED", hi
->handle
);
2457 if (((hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
))
2458 || (hi
->opserv_level
> 0))
2459 && ((argc
< 4) || irccasecmp(argv
[3], "staff"))) {
2460 reply("NSMSG_ALLOWAUTH_STAFF", hi
->handle
);
2463 dict_insert(nickserv_allow_auth_dict
, target
->nick
, hi
);
2464 reply("NSMSG_AUTH_ALLOWED", target
->nick
, hi
->handle
);
2465 send_message(target
, nickserv
, "NSMSG_AUTH_ALLOWED_MSG", hi
->handle
, hi
->handle
);
2466 if (nickserv_conf
.email_enabled
)
2467 send_message(target
, nickserv
, "NSMSG_AUTH_ALLOWED_EMAIL");
2469 if (dict_remove(nickserv_allow_auth_dict
, target
->nick
))
2470 reply("NSMSG_AUTH_NORMAL_ONLY", target
->nick
);
2472 reply("NSMSG_AUTH_UNSPECIAL", target
->nick
);
2474 for (n
=0; n
<allowauth_func_used
; n
++)
2475 allowauth_func_list
[n
](user
, target
, hi
, allowauth_func_list_extra
[n
]);
2479 static NICKSERV_FUNC(cmd_authcookie
)
2481 struct handle_info
*hi
;
2483 NICKSERV_MIN_PARMS(2);
2484 if (user
->handle_info
) {
2485 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2488 if (IsStamped(user
)) {
2489 /* Unauthenticated users might still have been stamped
2490 previously and could therefore have a hidden host;
2491 do not allow them to authenticate to an account. */
2492 reply("NSMSG_STAMPED_AUTHCOOKIE");
2495 if (!(hi
= get_handle_info(argv
[1]))) {
2496 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2499 if (!hi
->email_addr
) {
2500 reply("MSG_SET_EMAIL_ADDR");
2503 nickserv_make_cookie(user
, hi
, ALLOWAUTH
, NULL
, 0);
2507 static NICKSERV_FUNC(cmd_delcookie
)
2509 struct handle_info
*hi
;
2511 hi
= user
->handle_info
;
2513 reply("NSMSG_NO_COOKIE");
2516 switch (hi
->cookie
->type
) {
2519 reply("NSMSG_MUST_TIME_OUT");
2522 nickserv_eat_cookie(hi
->cookie
);
2523 reply("NSMSG_ATE_COOKIE");
2529 static NICKSERV_FUNC(cmd_odelcookie
)
2531 struct handle_info
*hi
;
2533 NICKSERV_MIN_PARMS(2);
2535 if (!(hi
= get_victim_oper(user
, argv
[1])))
2539 reply("NSMSG_NO_COOKIE_FOREIGN", hi
->handle
);
2543 switch (hi
->cookie
->type
) {
2545 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2547 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2549 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2550 /* Falied to update password in ldap, but still
2551 * updated it here.. what should we do? */
2552 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2557 if (nickserv_conf
.sync_log
)
2558 SyncLog("ACCOUNTACC %s", hi
->handle
);
2560 case PASSWORD_CHANGE
:
2567 reply("NSMSG_BAD_COOKIE_TYPE", hi
->cookie
->type
);
2568 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d for account %s.", hi
->cookie
->type
, hi
->handle
);
2572 nickserv_eat_cookie(hi
->cookie
);
2573 reply("NSMSG_ATE_FOREIGN_COOKIE", hi
->handle
);
2578 static NICKSERV_FUNC(cmd_resetpass
)
2580 struct handle_info
*hi
;
2581 char crypted
[MD5_CRYPT_LENGTH
];
2584 NICKSERV_MIN_PARMS(3);
2585 if(argc
>= 4 && !strcmp(argv
[3], "WEBLINK"))
2589 if (user
->handle_info
) {
2590 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2593 if (IsStamped(user
)) {
2594 /* Unauthenticated users might still have been stamped
2595 previously and could therefore have a hidden host;
2596 do not allow them to activate an account. */
2597 reply("NSMSG_STAMPED_RESETPASS");
2600 if (!(hi
= get_handle_info(argv
[1]))) {
2601 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2604 if (!hi
->email_addr
) {
2605 reply("MSG_SET_EMAIL_ADDR");
2608 cryptpass(argv
[2], crypted
);
2610 nickserv_make_cookie(user
, hi
, PASSWORD_CHANGE
, crypted
, weblink
);
2614 static NICKSERV_FUNC(cmd_cookie
)
2616 struct handle_info
*hi
;
2619 if ((argc
== 2) && (hi
= user
->handle_info
) && hi
->cookie
&& (hi
->cookie
->type
== EMAIL_CHANGE
)) {
2622 NICKSERV_MIN_PARMS(3);
2623 if (!(hi
= get_handle_info(argv
[1]))) {
2624 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2630 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2631 reply("NSMSG_HANDLE_SUSPENDED");
2636 reply("NSMSG_NO_COOKIE");
2640 /* Check validity of operation before comparing cookie to
2641 * prohibit guessing by authed users. */
2642 if (user
->handle_info
2643 && (hi
->cookie
->type
!= EMAIL_CHANGE
)
2644 && (hi
->cookie
->type
!= PASSWORD_CHANGE
)) {
2645 reply("NSMSG_CANNOT_COOKIE");
2649 if (strcmp(cookie
, hi
->cookie
->cookie
)) {
2650 reply("NSMSG_BAD_COOKIE");
2654 switch (hi
->cookie
->type
) {
2657 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2659 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2660 /* Falied to update email in ldap, but still
2661 * updated it here.. what should we do? */
2662 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2667 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2668 set_user_handle_info(user
, hi
, 1);
2669 reply("NSMSG_HANDLE_ACTIVATED");
2670 if (nickserv_conf
.sync_log
)
2671 SyncLog("ACCOUNTACC %s", hi
->handle
);
2673 case PASSWORD_CHANGE
:
2675 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2677 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2678 /* Falied to update email in ldap, but still
2679 * updated it here.. what should we do? */
2680 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2685 set_user_handle_info(user
, hi
, 1);
2686 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2687 reply("NSMSG_PASSWORD_CHANGED");
2688 if (nickserv_conf
.sync_log
)
2689 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
2693 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2695 if((rc
= ldap_do_modify(hi
->handle
, NULL
, hi
->cookie
->data
)) != LDAP_SUCCESS
) {
2696 /* Falied to update email in ldap, but still
2697 * updated it here.. what should we do? */
2698 reply("NSMSG_LDAP_FAIL_SEND_EMAIL", ldap_err2string(rc
));
2703 if (!hi
->email_addr
&& nickserv_conf
.sync_log
) {
2705 * This should only happen if an OREGISTER was sent. Require
2706 * email must be enabled! - SiRVulcaN
2708 if (nickserv_conf
.sync_log
)
2709 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, hi
->cookie
->data
, user
->info
);
2712 nickserv_set_email_addr(hi
, hi
->cookie
->data
);
2713 reply("NSMSG_EMAIL_CHANGED");
2714 if (nickserv_conf
.sync_log
)
2715 SyncLog("EMAILCHANGE %s %s", hi
->handle
, hi
->cookie
->data
);
2718 char *mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2719 set_user_handle_info(user
, hi
, 1);
2720 nickserv_addmask(user
, hi
, mask
);
2721 reply("NSMSG_AUTH_SUCCESS");
2726 reply("NSMSG_BAD_COOKIE_TYPE", hi
->cookie
->type
);
2727 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d for account %s.", hi
->cookie
->type
, hi
->handle
);
2731 nickserv_eat_cookie(hi
->cookie
);
2733 process_adduser_pending(user
);
2738 static NICKSERV_FUNC(cmd_oregnick
) {
2740 struct handle_info
*target
;
2741 struct nick_info
*ni
;
2743 NICKSERV_MIN_PARMS(3);
2744 if (!(target
= modcmd_get_handle_info(user
, argv
[1])))
2747 if (!is_registerable_nick(nick
)) {
2748 reply("NSMSG_BAD_NICK", nick
);
2751 ni
= dict_find(nickserv_nick_dict
, nick
, NULL
);
2753 reply("NSMSG_NICK_EXISTS", nick
);
2756 register_nick(nick
, target
);
2757 reply("NSMSG_OREGNICK_SUCCESS", nick
, target
->handle
);
2761 static NICKSERV_FUNC(cmd_regnick
) {
2763 struct nick_info
*ni
;
2765 if (!is_registerable_nick(user
->nick
)) {
2766 reply("NSMSG_BAD_NICK", user
->nick
);
2769 /* count their nicks, see if it's too many */
2770 for (n
=0,ni
=user
->handle_info
->nicks
; ni
; n
++,ni
=ni
->next
) ;
2771 if (n
>= nickserv_conf
.nicks_per_handle
) {
2772 reply("NSMSG_TOO_MANY_NICKS");
2775 ni
= dict_find(nickserv_nick_dict
, user
->nick
, NULL
);
2777 reply("NSMSG_NICK_EXISTS", user
->nick
);
2780 register_nick(user
->nick
, user
->handle_info
);
2781 reply("NSMSG_REGNICK_SUCCESS", user
->nick
);
2785 static NICKSERV_FUNC(cmd_pass
)
2787 struct handle_info
*hi
;
2788 char *old_pass
, *new_pass
;
2789 char crypted
[MD5_CRYPT_LENGTH
+1];
2794 NICKSERV_MIN_PARMS(3);
2795 hi
= user
->handle_info
;
2799 if (!is_secure_password(hi
->handle
, new_pass
, user
)) return 0;
2802 if(nickserv_conf
.ldap_enable
) {
2803 ldap_result
= ldap_check_auth(hi
->handle
, old_pass
);
2804 if(ldap_result
!= LDAP_SUCCESS
) {
2805 if(ldap_result
== LDAP_INVALID_CREDENTIALS
)
2806 reply("NSMSG_PASSWORD_INVALID");
2808 reply("NSMSG_LDAP_FAIL", ldap_err2string(ldap_result
));
2813 if (!checkpass(old_pass
, hi
->passwd
)) {
2814 argv
[1] = "BADPASS";
2815 reply("NSMSG_PASSWORD_INVALID");
2818 cryptpass(new_pass
, crypted
);
2820 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2822 if((rc
= ldap_do_modify(hi
->handle
, crypted
, NULL
)) != LDAP_SUCCESS
) {
2823 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2828 //cryptpass(new_pass, hi->passwd);
2829 strcpy(hi
->passwd
, crypted
);
2830 if (nickserv_conf
.sync_log
)
2831 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
2833 reply("NSMSG_PASS_SUCCESS");
2838 nickserv_addmask(struct userNode
*user
, struct handle_info
*hi
, const char *mask
)
2841 char *new_mask
= canonicalize_hostmask(strdup(mask
));
2842 for (i
=0; i
<hi
->masks
->used
; i
++) {
2843 if (!irccasecmp(new_mask
, hi
->masks
->list
[i
])) {
2844 send_message(user
, nickserv
, "NSMSG_ADDMASK_ALREADY", new_mask
);
2849 string_list_append(hi
->masks
, new_mask
);
2850 send_message(user
, nickserv
, "NSMSG_ADDMASK_SUCCESS", new_mask
);
2854 static NICKSERV_FUNC(cmd_addmask
)
2857 char *mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2858 int res
= nickserv_addmask(user
, user
->handle_info
, mask
);
2862 if (!is_gline(argv
[1])) {
2863 reply("NSMSG_MASK_INVALID", argv
[1]);
2866 return nickserv_addmask(user
, user
->handle_info
, argv
[1]);
2870 static NICKSERV_FUNC(cmd_oaddmask
)
2872 struct handle_info
*hi
;
2874 NICKSERV_MIN_PARMS(3);
2875 if (!(hi
= get_victim_oper(user
, argv
[1])))
2877 return nickserv_addmask(user
, hi
, argv
[2]);
2881 nickserv_delmask(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, const char *del_mask
, int force
)
2884 for (i
=0; i
<hi
->masks
->used
; i
++) {
2885 if (!strcmp(del_mask
, hi
->masks
->list
[i
])) {
2886 char *old_mask
= hi
->masks
->list
[i
];
2887 if (hi
->masks
->used
== 1 && !force
) {
2888 reply("NSMSG_DELMASK_NOTLAST");
2891 hi
->masks
->list
[i
] = hi
->masks
->list
[--hi
->masks
->used
];
2892 reply("NSMSG_DELMASK_SUCCESS", old_mask
);
2897 reply("NSMSG_DELMASK_NOT_FOUND");
2901 static NICKSERV_FUNC(cmd_delmask
)
2903 NICKSERV_MIN_PARMS(2);
2904 return nickserv_delmask(cmd
, user
, user
->handle_info
, argv
[1], 0);
2907 static NICKSERV_FUNC(cmd_odelmask
)
2909 struct handle_info
*hi
;
2910 NICKSERV_MIN_PARMS(3);
2911 if (!(hi
= get_victim_oper(user
, argv
[1])))
2913 return nickserv_delmask(cmd
, user
, hi
, argv
[2], 1);
2917 nickserv_addsslfp(struct userNode
*user
, struct handle_info
*hi
, const char *sslfp
)
2920 char *new_sslfp
= strdup(sslfp
);
2921 for (i
=0; i
<hi
->sslfps
->used
; i
++) {
2922 if (!irccasecmp(new_sslfp
, hi
->sslfps
->list
[i
])) {
2923 send_message(user
, nickserv
, "NSMSG_ADDSSLFP_ALREADY", new_sslfp
);
2928 string_list_append(hi
->sslfps
, new_sslfp
);
2929 send_message(user
, nickserv
, "NSMSG_ADDSSLFP_SUCCESS", new_sslfp
);
2933 static NICKSERV_FUNC(cmd_addsslfp
)
2935 NICKSERV_MIN_PARMS((user
->sslfp
? 1 : 2));
2936 if ((argc
< 2) && (user
->sslfp
)) {
2937 int res
= nickserv_addsslfp(user
, user
->handle_info
, user
->sslfp
);
2940 return nickserv_addsslfp(user
, user
->handle_info
, argv
[1]);
2944 static NICKSERV_FUNC(cmd_oaddsslfp
)
2946 struct handle_info
*hi
;
2948 NICKSERV_MIN_PARMS(3);
2949 if (!(hi
= get_victim_oper(user
, argv
[1])))
2951 return nickserv_addsslfp(user
, hi
, argv
[2]);
2955 nickserv_delsslfp(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, const char *del_sslfp
)
2958 for (i
=0; i
<hi
->sslfps
->used
; i
++) {
2959 if (!irccasecmp(del_sslfp
, hi
->sslfps
->list
[i
])) {
2960 char *old_sslfp
= hi
->sslfps
->list
[i
];
2961 hi
->sslfps
->list
[i
] = hi
->sslfps
->list
[--hi
->sslfps
->used
];
2962 reply("NSMSG_DELSSLFP_SUCCESS", old_sslfp
);
2967 reply("NSMSG_DELSSLFP_NOT_FOUND");
2971 static NICKSERV_FUNC(cmd_delsslfp
)
2973 NICKSERV_MIN_PARMS((user
->sslfp
? 1 : 2));
2974 if ((argc
< 2) && (user
->sslfp
)) {
2975 return nickserv_delsslfp(cmd
, user
, user
->handle_info
, user
->sslfp
);
2977 return nickserv_delsslfp(cmd
, user
, user
->handle_info
, argv
[1]);
2981 static NICKSERV_FUNC(cmd_odelsslfp
)
2983 struct handle_info
*hi
;
2984 NICKSERV_MIN_PARMS(3);
2985 if (!(hi
= get_victim_oper(user
, argv
[1])))
2987 return nickserv_delsslfp(cmd
, user
, hi
, argv
[2]);
2991 nickserv_modify_handle_flags(struct userNode
*user
, struct userNode
*bot
, const char *str
, unsigned long *padded
, unsigned long *premoved
) {
2992 unsigned int nn
, add
= 1, pos
;
2993 unsigned long added
, removed
, flag
;
2995 for (added
=removed
=nn
=0; str
[nn
]; nn
++) {
2997 case '+': add
= 1; break;
2998 case '-': add
= 0; break;
3000 if (!(pos
= handle_inverse_flags
[(unsigned char)str
[nn
]])) {
3001 send_message(user
, bot
, "NSMSG_INVALID_FLAG", str
[nn
]);
3004 if (user
&& (user
->handle_info
->opserv_level
< flag_access_levels
[pos
-1])) {
3005 /* cheesy avoidance of looking up the flag name.. */
3006 send_message(user
, bot
, "NSMSG_FLAG_PRIVILEGED", str
[nn
]);
3009 flag
= 1 << (pos
- 1);
3011 added
|= flag
, removed
&= ~flag
;
3013 removed
|= flag
, added
&= ~flag
;
3018 *premoved
= removed
;
3023 nickserv_apply_flags(struct userNode
*user
, struct handle_info
*hi
, const char *flags
)
3025 unsigned long before
, after
, added
, removed
;
3026 struct userNode
*uNode
;
3028 before
= hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
);
3029 if (!nickserv_modify_handle_flags(user
, nickserv
, flags
, &added
, &removed
))
3031 hi
->flags
= (hi
->flags
| added
) & ~removed
;
3032 after
= hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
);
3034 /* Strip helping flag if they're only a support helper and not
3035 * currently in #support. */
3036 if (HANDLE_FLAGGED(hi
, HELPING
) && (after
== HI_FLAG_SUPPORT_HELPER
)) {
3037 struct channelList
*schannels
;
3039 schannels
= chanserv_support_channels();
3040 for (ii
= 0; ii
< schannels
->used
; ++ii
)
3041 if (find_handle_in_channel(schannels
->list
[ii
], hi
, NULL
))
3043 if (ii
== schannels
->used
)
3044 HANDLE_CLEAR_FLAG(hi
, HELPING
);
3047 if (after
&& !before
) {
3048 /* Add user to current helper list. */
3049 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
3050 userList_append(&curr_helpers
, uNode
);
3051 } else if (!after
&& before
) {
3052 /* Remove user from current helper list. */
3053 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
3054 userList_remove(&curr_helpers
, uNode
);
3061 set_list(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, int override
)
3065 char *set_display
[] = {
3066 "INFO", "WIDTH", "TABLEWIDTH", "COLOR", "PRIVMSG", "STYLE",
3067 "EMAIL", "ANNOUNCEMENTS", "AUTOHIDE", "MAXLOGINS", "LANGUAGE",
3068 "FAKEHOST", "TITLE", "EPITHET", "ADVANCED"
3071 reply("NSMSG_SETTING_LIST");
3072 reply("NSMSG_SETTING_LIST_HEADER");
3074 /* Do this so options are presented in a consistent order. */
3075 for (i
= 0; i
< ArrayLength(set_display
); ++i
)
3076 if ((opt
= dict_find(nickserv_opt_dict
, set_display
[i
], NULL
)))
3077 opt(cmd
, user
, hi
, override
, 0, NULL
);
3078 reply("NSMSG_SETTING_LIST_END");
3081 static NICKSERV_FUNC(cmd_set
)
3083 struct handle_info
*hi
;
3086 hi
= user
->handle_info
;
3088 set_list(cmd
, user
, hi
, 0);
3091 if (!(opt
= dict_find(nickserv_opt_dict
, argv
[1], NULL
))) {
3092 reply("NSMSG_INVALID_OPTION", argv
[1]);
3095 return opt(cmd
, user
, hi
, 0, argc
-1, argv
+1);
3098 static NICKSERV_FUNC(cmd_oset
)
3100 struct handle_info
*hi
;
3103 NICKSERV_MIN_PARMS(2);
3105 if (!(hi
= get_victim_oper(user
, argv
[1])))
3109 set_list(cmd
, user
, hi
, 0);
3113 if (!(opt
= dict_find(nickserv_opt_dict
, argv
[2], NULL
))) {
3114 reply("NSMSG_INVALID_OPTION", argv
[2]);
3118 return opt(cmd
, user
, hi
, 1, argc
-2, argv
+2);
3121 static OPTION_FUNC(opt_info
)
3125 if ((argv
[1][0] == '*') && (argv
[1][1] == 0)) {
3127 hi
->infoline
= NULL
;
3129 hi
->infoline
= strdup(unsplit_string(argv
+1, argc
-1, NULL
));
3133 info
= hi
->infoline
? hi
->infoline
: user_find_message(user
, "MSG_NONE");
3134 reply("NSMSG_SET_INFO", info
);
3138 static OPTION_FUNC(opt_width
)
3141 hi
->screen_width
= strtoul(argv
[1], NULL
, 0);
3143 if ((hi
->screen_width
> 0) && (hi
->screen_width
< MIN_LINE_SIZE
))
3144 hi
->screen_width
= MIN_LINE_SIZE
;
3145 else if (hi
->screen_width
> MAX_LINE_SIZE
)
3146 hi
->screen_width
= MAX_LINE_SIZE
;
3148 reply("NSMSG_SET_WIDTH", hi
->screen_width
);
3152 static OPTION_FUNC(opt_tablewidth
)
3155 hi
->table_width
= strtoul(argv
[1], NULL
, 0);
3157 if ((hi
->table_width
> 0) && (hi
->table_width
< MIN_LINE_SIZE
))
3158 hi
->table_width
= MIN_LINE_SIZE
;
3159 else if (hi
->screen_width
> MAX_LINE_SIZE
)
3160 hi
->table_width
= MAX_LINE_SIZE
;
3162 reply("NSMSG_SET_TABLEWIDTH", hi
->table_width
);
3166 static OPTION_FUNC(opt_color
)
3169 if (enabled_string(argv
[1]))
3170 HANDLE_SET_FLAG(hi
, MIRC_COLOR
);
3171 else if (disabled_string(argv
[1]))
3172 HANDLE_CLEAR_FLAG(hi
, MIRC_COLOR
);
3174 reply("MSG_INVALID_BINARY", argv
[1]);
3179 reply("NSMSG_SET_COLOR", user_find_message(user
, HANDLE_FLAGGED(hi
, MIRC_COLOR
) ? "MSG_ON" : "MSG_OFF"));
3183 static OPTION_FUNC(opt_privmsg
)
3186 if (enabled_string(argv
[1]))
3187 HANDLE_SET_FLAG(hi
, USE_PRIVMSG
);
3188 else if (disabled_string(argv
[1]))
3189 HANDLE_CLEAR_FLAG(hi
, USE_PRIVMSG
);
3191 reply("MSG_INVALID_BINARY", argv
[1]);
3196 reply("NSMSG_SET_PRIVMSG", user_find_message(user
, HANDLE_FLAGGED(hi
, USE_PRIVMSG
) ? "MSG_ON" : "MSG_OFF"));
3200 static OPTION_FUNC(opt_autohide
)
3203 if (enabled_string(argv
[1]))
3204 HANDLE_SET_FLAG(hi
, AUTOHIDE
);
3205 else if (disabled_string(argv
[1]))
3206 HANDLE_CLEAR_FLAG(hi
, AUTOHIDE
);
3208 reply("MSG_INVALID_BINARY", argv
[1]);
3213 reply("NSMSG_SET_AUTOHIDE", user_find_message(user
, HANDLE_FLAGGED(hi
, AUTOHIDE
) ? "MSG_ON" : "MSG_OFF"));
3217 static OPTION_FUNC(opt_style
)
3222 if (!irccasecmp(argv
[1], "Clean"))
3223 hi
->userlist_style
= HI_STYLE_CLEAN
;
3224 else if (!irccasecmp(argv
[1], "Advanced"))
3225 hi
->userlist_style
= HI_STYLE_ADVANCED
;
3226 else if (!irccasecmp(argv
[1], "Classic"))
3227 hi
->userlist_style
= HI_STYLE_CLASSIC
;
3228 else /* Default to normal */
3229 hi
->userlist_style
= HI_STYLE_NORMAL
;
3230 } /* TODO: give error if unknow style is chosen */
3232 switch (hi
->userlist_style
) {
3233 case HI_STYLE_ADVANCED
:
3236 case HI_STYLE_CLASSIC
:
3239 case HI_STYLE_CLEAN
:
3242 case HI_STYLE_NORMAL
:
3247 reply("NSMSG_SET_STYLE", style
);
3251 static OPTION_FUNC(opt_announcements
)
3256 if (enabled_string(argv
[1]))
3257 hi
->announcements
= 'y';
3258 else if (disabled_string(argv
[1]))
3259 hi
->announcements
= 'n';
3260 else if (!strcmp(argv
[1], "?") || !irccasecmp(argv
[1], "default"))
3261 hi
->announcements
= '?';
3263 reply("NSMSG_INVALID_ANNOUNCE", argv
[1]);
3268 switch (hi
->announcements
) {
3269 case 'y': choice
= user_find_message(user
, "MSG_ON"); break;
3270 case 'n': choice
= user_find_message(user
, "MSG_OFF"); break;
3271 case '?': choice
= "default"; break;
3272 default: choice
= "unknown"; break;
3274 reply("NSMSG_SET_ANNOUNCEMENTS", choice
);
3278 static OPTION_FUNC(opt_password
)
3280 char crypted
[MD5_CRYPT_LENGTH
+1];
3285 reply("NSMSG_USE_CMD_PASS");
3289 cryptpass(argv
[1], crypted
);
3291 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
3293 if((rc
= ldap_do_modify(hi
->handle
, crypted
, NULL
)) != LDAP_SUCCESS
) {
3294 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3299 strcpy(hi
->passwd
, crypted
);
3300 if (nickserv_conf
.sync_log
)
3301 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
3303 reply("NSMSG_SET_PASSWORD", "***");
3307 static OPTION_FUNC(opt_flags
)
3310 unsigned int ii
, flen
;
3313 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3318 nickserv_apply_flags(user
, hi
, argv
[1]);
3320 for (ii
= flen
= 0; handle_flags
[ii
]; ii
++)
3321 if (hi
->flags
& (1 << ii
))
3322 flags
[flen
++] = handle_flags
[ii
];
3325 reply("NSMSG_SET_FLAGS", flags
);
3327 reply("NSMSG_SET_FLAGS", user_find_message(user
, "MSG_NONE"));
3331 static OPTION_FUNC(opt_email
)
3335 if (!valid_email(argv
[1])) {
3336 reply("NSMSG_BAD_EMAIL_ADDR");
3339 if ((str
= mail_prohibited_address(argv
[1]))) {
3340 reply("NSMSG_EMAIL_PROHIBITED", argv
[1], str
);
3343 if (hi
->email_addr
&& !irccasecmp(hi
->email_addr
, argv
[1]))
3344 reply("NSMSG_EMAIL_SAME");
3346 nickserv_make_cookie(user
, hi
, EMAIL_CHANGE
, argv
[1], 0);
3349 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
3351 if((rc
= ldap_do_modify(hi
->handle
, NULL
, argv
[1])) != LDAP_SUCCESS
) {
3352 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3357 nickserv_set_email_addr(hi
, argv
[1]);
3359 nickserv_eat_cookie(hi
->cookie
);
3360 reply("NSMSG_SET_EMAIL", visible_email_addr(user
, hi
));
3363 reply("NSMSG_SET_EMAIL", visible_email_addr(user
, hi
));
3367 static OPTION_FUNC(opt_maxlogins
)
3369 unsigned char maxlogins
;
3371 maxlogins
= strtoul(argv
[1], NULL
, 0);
3372 if ((maxlogins
> nickserv_conf
.hard_maxlogins
) && !override
) {
3373 reply("NSMSG_BAD_MAX_LOGINS", nickserv_conf
.hard_maxlogins
);
3376 hi
->maxlogins
= maxlogins
;
3378 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
3379 reply("NSMSG_SET_MAXLOGINS", maxlogins
);
3383 static OPTION_FUNC(opt_advanced
)
3386 if (enabled_string(argv
[1]))
3387 HANDLE_SET_FLAG(hi
, ADVANCED
);
3388 else if (disabled_string(argv
[1]))
3389 HANDLE_CLEAR_FLAG(hi
, ADVANCED
);
3391 reply("MSG_INVALID_BINARY", argv
[1]);
3396 reply("NSMSG_SET_ADVANCED", user_find_message(user
, HANDLE_FLAGGED(hi
, ADVANCED
) ? "MSG_ON" : "MSG_OFF"));
3400 static OPTION_FUNC(opt_language
)
3402 struct language
*lang
;
3404 lang
= language_find(argv
[1]);
3405 if (irccasecmp(lang
->name
, argv
[1]))
3406 reply("NSMSG_LANGUAGE_NOT_FOUND", argv
[1], lang
->name
);
3407 hi
->language
= lang
;
3409 reply("NSMSG_SET_LANGUAGE", hi
->language
->name
);
3413 static OPTION_FUNC(opt_karma
)
3416 send_message(user
, nickserv
, "MSG_SETTING_PRIVILEGED", argv
[0]);
3421 if (argv
[1][0] == '+' && isdigit(argv
[1][1])) {
3422 hi
->karma
+= strtoul(argv
[1] + 1, NULL
, 10);
3423 } else if (argv
[1][0] == '-' && isdigit(argv
[1][1])) {
3424 hi
->karma
-= strtoul(argv
[1] + 1, NULL
, 10);
3426 send_message(user
, nickserv
, "NSMSG_INVALID_KARMA", argv
[1]);
3430 send_message(user
, nickserv
, "NSMSG_SET_KARMA", hi
->karma
);
3434 /* Called from opserv from cmd_access */
3436 oper_try_set_access(struct userNode
*user
, struct userNode
*bot
, struct handle_info
*target
, unsigned int new_level
) {
3437 if (!oper_has_access(user
, bot
, nickserv_conf
.modoper_level
, 0))
3439 if ((user
->handle_info
->opserv_level
< target
->opserv_level
)
3440 || ((user
->handle_info
->opserv_level
== target
->opserv_level
)
3441 && (user
->handle_info
->opserv_level
< 1000))) {
3442 send_message(user
, bot
, "MSG_USER_OUTRANKED", target
->handle
);
3445 if ((user
->handle_info
->opserv_level
< new_level
)
3446 || ((user
->handle_info
->opserv_level
== new_level
)
3447 && (user
->handle_info
->opserv_level
< 1000))) {
3448 send_message(user
, bot
, "NSMSG_OPSERV_LEVEL_BAD");
3451 if (user
->handle_info
== target
) {
3452 send_message(user
, bot
, "MSG_STUPID_ACCESS_CHANGE");
3456 if(nickserv_conf
.ldap_enable
&& *(nickserv_conf
.ldap_oper_group_dn
) && *(nickserv_conf
.ldap_admin_dn
)) {
3458 if(new_level
> nickserv_conf
.ldap_oper_group_level
)
3459 rc
= ldap_add2group(target
->handle
, nickserv_conf
.ldap_oper_group_dn
);
3461 rc
= ldap_delfromgroup(target
->handle
, nickserv_conf
.ldap_oper_group_dn
);
3462 if(rc
!= LDAP_SUCCESS
&& rc
!= LDAP_TYPE_OR_VALUE_EXISTS
&& rc
!= LDAP_NO_SUCH_ATTRIBUTE
) {
3463 send_message(user
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3467 if(nickserv_conf
.ldap_enable
&& *(nickserv_conf
.ldap_field_oslevel
) && *(nickserv_conf
.ldap_admin_dn
)) {
3469 if((rc
= ldap_do_oslevel(target
->handle
, new_level
, target
->opserv_level
)) != LDAP_SUCCESS
) {
3470 send_message(user
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3475 if (target
->opserv_level
== new_level
)
3477 log_module(NS_LOG
, LOG_INFO
, "Account %s setting oper level for account %s to %d (from %d).",
3478 user
->handle_info
->handle
, target
->handle
, new_level
, target
->opserv_level
);
3479 target
->opserv_level
= new_level
;
3483 static OPTION_FUNC(opt_level
)
3488 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3492 res
= (argc
> 1) ? oper_try_set_access(user
, nickserv
, hi
, strtoul(argv
[1], NULL
, 0)) : 0;
3493 reply("NSMSG_SET_LEVEL", hi
->opserv_level
);
3497 static OPTION_FUNC(opt_epithet
)
3499 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_epithet_level
, 0)) {
3501 struct userNode
*target
, *next_un
;
3504 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3508 epithet
= unsplit_string(argv
+1, argc
-1, NULL
);
3512 if ((epithet
[0] == '*') && !epithet
[1])
3515 hi
->epithet
= strdup(epithet
);
3517 for (target
= hi
->users
; target
; target
= next_un
) {
3518 irc_swhois(nickserv
, target
, hi
->epithet
);
3520 next_un
= target
->next_authed
;
3525 reply("NSMSG_SET_EPITHET", hi
->epithet
);
3527 reply("NSMSG_SET_EPITHET", user_find_message(user
, "MSG_NONE"));
3531 static OPTION_FUNC(opt_title
)
3537 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_title_level
, 0)) {
3539 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3544 if(!strcmp(title
, "*")) {
3546 hi
->fakehost
= NULL
;
3549 if (strchr(title
, '.')) {
3550 reply("NSMSG_TITLE_INVALID");
3553 /* Alphanumeric titles only. */
3554 for(sptr
= title
; *sptr
; sptr
++) {
3555 if(!isalnum(*sptr
) && *sptr
!= '-') {
3556 reply("NSMSG_TITLE_INVALID");
3560 if ((strlen(user
->handle_info
->handle
) + strlen(title
) +
3561 strlen(nickserv_conf
.titlehost_suffix
) + 2) > HOSTLEN
) {
3562 reply("NSMSG_TITLE_TRUNCATED");
3566 hi
->fakehost
= malloc(strlen(title
)+2);
3567 hi
->fakehost
[0] = '.';
3568 strcpy(hi
->fakehost
+1, title
);
3571 } else if (hi
->fakehost
&& (hi
->fakehost
[0] == '.'))
3572 title
= hi
->fakehost
+ 1;
3574 /* If theres no title set then the default title will therefore
3575 be the first part of hidden_host in x3.conf, so for
3576 consistency with opt_fakehost we will print this here.
3577 This isnt actually used in P10, its just handled to keep from crashing... */
3578 char *hs
, *hidden_suffix
, *rest
;
3580 hs
= conf_get_data("server/hidden_host", RECDB_QSTRING
);
3581 hidden_suffix
= strdup(hs
);
3583 /* Yes we do this twice */
3584 if((rest
= strchr(hidden_suffix
, '.')))
3587 title
= hidden_suffix
;
3591 /* A lame default if someone configured hidden_host to something lame */
3592 title
= strdup("users");
3593 free(hidden_suffix
);
3599 none
= user_find_message(user
, "MSG_NONE");
3600 send_message(user
, nickserv
, "NSMSG_SET_TITLE", title
? title
: none
);
3605 check_vhost(char *vhost
, struct userNode
*user
, struct svccmd
*cmd
)
3609 // check for a dot in the vhost
3610 if(strchr(vhost
, '.') == NULL
) {
3611 reply("NSMSG_NOT_VALID_FAKEHOST_DOT", vhost
);
3615 // check for a @ in the vhost
3616 if(strchr(vhost
, '@') != NULL
) {
3617 reply("NSMSG_NOT_VALID_FAKEHOST_AT", vhost
);
3621 // check for denied words, inspired by monk at paki.sex
3622 for(y
= 0; y
< nickserv_conf
.denied_fakehost_words
->used
; y
++) {
3623 if(strstr(vhost
, nickserv_conf
.denied_fakehost_words
->list
[y
]) != NULL
) {
3624 reply("NSMSG_DENIED_FAKEHOST_WORD", vhost
, nickserv_conf
.denied_fakehost_words
->list
[y
]);
3629 // check for ircu's HOSTLEN length.
3630 if(strlen(vhost
) >= HOSTLEN
) {
3631 reply("NSMSG_NOT_VALID_FAKEHOST_LEN", vhost
);
3635 /* This can be handled by the regex now if desired.
3636 if (vhost[strspn(vhost, "0123456789.")]) {
3637 hostname = vhost + strlen(vhost);
3638 for (depth = 1; depth && (hostname > vhost); depth--) {
3640 while ((hostname > vhost) && (*hostname != '.')) hostname--;
3643 if (*hostname == '.') hostname++; * advance past last dot we saw *
3644 if(strlen(hostname) > 4) {
3645 reply("NSMSG_NOT_VALID_FAKEHOST_TLD_LEN", vhost);
3650 /* test either regex or as valid handle */
3651 if (nickserv_conf
.valid_fakehost_regex_set
) {
3652 int err
= regexec(&nickserv_conf
.valid_fakehost_regex
, vhost
, 0, 0, 0);
3655 buff
[regerror(err
, &nickserv_conf
.valid_fakehost_regex
, buff
, sizeof(buff
))] = 0;
3656 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
3658 if(err
== REG_NOMATCH
) {
3659 reply("NSMSG_NOT_VALID_FAKEHOST_REGEX", vhost
);
3668 static OPTION_FUNC(opt_fakehost
)
3672 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_fakehost_level
, 0)) {
3674 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3679 if ((strlen(fake
) > HOSTLEN
) || (fake
[0] == '.')) {
3680 reply("NSMSG_FAKEHOST_INVALID", HOSTLEN
);
3683 if (!strcmp(fake
, "*")) {
3686 hi
->fakehost
= NULL
;
3689 else if (!check_vhost(argv
[1], user
, cmd
)) {
3690 /* check_vhost takes care of error reply */
3696 hi
->fakehost
= strdup(fake
);
3699 fake
= hi
->fakehost
;
3701 fake
= generate_fakehost(hi
);
3703 /* Tell them we set the host */
3705 fake
= user_find_message(user
, "MSG_NONE");
3706 reply("NSMSG_SET_FAKEHOST", fake
);
3710 static OPTION_FUNC(opt_note
)
3713 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3718 char *text
= unsplit_string(argv
+ 1, argc
- 1, NULL
);
3723 if ((text
[0] == '*') && !text
[1])
3726 if (!(hi
->note
= nickserv_add_note(user
->handle_info
->handle
, now
, text
)))
3731 reply("NSMSG_SET_NOTE", hi
->note
? hi
->note
->note
: user_find_message(user
, "MSG_NONE"));
3735 static NICKSERV_FUNC(cmd_reclaim
)
3737 struct handle_info
*hi
;
3738 struct nick_info
*ni
;
3739 struct userNode
*victim
;
3741 NICKSERV_MIN_PARMS(2);
3742 hi
= user
->handle_info
;
3743 ni
= dict_find(nickserv_nick_dict
, argv
[1], 0);
3745 reply("NSMSG_UNKNOWN_NICK", argv
[1]);
3748 if (ni
->owner
!= user
->handle_info
) {
3749 reply("NSMSG_NOT_YOUR_NICK", ni
->nick
);
3752 victim
= GetUserH(ni
->nick
);
3754 reply("MSG_NICK_UNKNOWN", ni
->nick
);
3757 if (victim
== user
) {
3758 reply("NSMSG_NICK_USER_YOU");
3761 nickserv_reclaim(victim
, ni
, nickserv_conf
.reclaim_action
);
3762 switch (nickserv_conf
.reclaim_action
) {
3763 case RECLAIM_NONE
: reply("NSMSG_RECLAIMED_NONE"); break;
3764 case RECLAIM_WARN
: reply("NSMSG_RECLAIMED_WARN", victim
->nick
); break;
3765 case RECLAIM_SVSNICK
: reply("NSMSG_RECLAIMED_SVSNICK", victim
->nick
); break;
3766 case RECLAIM_KILL
: reply("NSMSG_RECLAIMED_KILL", victim
->nick
); break;
3771 static NICKSERV_FUNC(cmd_unregnick
)
3774 struct handle_info
*hi
;
3775 struct nick_info
*ni
;
3777 hi
= user
->handle_info
;
3778 nick
= (argc
< 2) ? user
->nick
: (const char*)argv
[1];
3779 ni
= dict_find(nickserv_nick_dict
, nick
, NULL
);
3781 reply("NSMSG_UNKNOWN_NICK", nick
);
3784 if (hi
!= ni
->owner
) {
3785 reply("NSMSG_NOT_YOUR_NICK", nick
);
3788 reply("NSMSG_UNREGNICK_SUCCESS", ni
->nick
);
3793 static NICKSERV_FUNC(cmd_ounregnick
)
3795 struct nick_info
*ni
;
3797 NICKSERV_MIN_PARMS(2);
3798 if (!(ni
= get_nick_info(argv
[1]))) {
3799 reply("NSMSG_NICK_NOT_REGISTERED", argv
[1]);
3802 if (!oper_outranks(user
, ni
->owner
))
3804 reply("NSMSG_UNREGNICK_SUCCESS", ni
->nick
);
3809 static NICKSERV_FUNC(cmd_unregister
)
3811 struct handle_info
*hi
;
3814 NICKSERV_MIN_PARMS(2);
3815 hi
= user
->handle_info
;
3818 if (checkpass(passwd
, hi
->passwd
)) {
3819 if(nickserv_unregister_handle(hi
, user
, cmd
->parent
->bot
))
3824 log_module(NS_LOG
, LOG_INFO
, "Account '%s' tried to unregister with the wrong password.", hi
->handle
);
3825 reply("NSMSG_PASSWORD_INVALID");
3830 static NICKSERV_FUNC(cmd_ounregister
)
3832 struct handle_info
*hi
;
3833 char reason
[MAXLEN
];
3836 NICKSERV_MIN_PARMS(2);
3837 if (!(hi
= get_victim_oper(user
, argv
[1])))
3840 if (HANDLE_FLAGGED(hi
, NODELETE
)) {
3841 reply("NSMSG_UNREGISTER_NODELETE", hi
->handle
);
3845 force
= IsOper(user
) && (argc
> 2) && !irccasecmp(argv
[2], "force");
3847 ((hi
->flags
& nickserv_conf
.ounregister_flags
)
3849 || (hi
->last_quit_host
[0] && ((unsigned)(now
- hi
->lastseen
) < nickserv_conf
.ounregister_inactive
)))) {
3850 reply((IsOper(user
) ? "NSMSG_UNREGISTER_MUST_FORCE" : "NSMSG_UNREGISTER_CANNOT_FORCE"), hi
->handle
);
3853 snprintf(reason
, sizeof(reason
), "%s unregistered account %s.", user
->handle_info
->handle
, hi
->handle
);
3854 global_message(MESSAGE_RECIPIENT_STAFF
, reason
);
3855 if(nickserv_unregister_handle(hi
, user
, cmd
->parent
->bot
))
3861 static NICKSERV_FUNC(cmd_status
)
3863 if (nickserv_conf
.disable_nicks
) {
3864 reply("NSMSG_GLOBAL_STATS_NONICK",
3865 dict_size(nickserv_handle_dict
));
3867 if (user
->handle_info
) {
3869 struct nick_info
*ni
;
3870 for (ni
=user
->handle_info
->nicks
; ni
; ni
=ni
->next
) cnt
++;
3871 reply("NSMSG_HANDLE_STATS", cnt
);
3873 reply("NSMSG_HANDLE_NONE");
3875 reply("NSMSG_GLOBAL_STATS",
3876 dict_size(nickserv_handle_dict
),
3877 dict_size(nickserv_nick_dict
));
3882 static NICKSERV_FUNC(cmd_ghost
)
3884 struct userNode
*target
;
3885 char reason
[MAXLEN
];
3887 NICKSERV_MIN_PARMS(2);
3888 if (!(target
= GetUserH(argv
[1]))) {
3889 reply("MSG_NICK_UNKNOWN", argv
[1]);
3892 if (target
== user
) {
3893 reply("NSMSG_CANNOT_GHOST_SELF");
3896 if (!target
->handle_info
|| (target
->handle_info
!= user
->handle_info
)) {
3897 reply("NSMSG_CANNOT_GHOST_USER", target
->nick
);
3900 snprintf(reason
, sizeof(reason
), "Ghost kill on account %s (requested by %s).", target
->handle_info
->handle
, user
->nick
);
3901 DelUser(target
, nickserv
, 1, reason
);
3902 reply("NSMSG_GHOST_KILLED", argv
[1]);
3906 static NICKSERV_FUNC(cmd_vacation
)
3908 HANDLE_SET_FLAG(user
->handle_info
, FROZEN
);
3909 reply("NSMSG_ON_VACATION");
3914 nickserv_saxdb_write(struct saxdb_context
*ctx
) {
3916 struct handle_info
*hi
;
3919 for (it
= dict_first(nickserv_handle_dict
); it
; it
= iter_next(it
)) {
3921 saxdb_start_record(ctx
, iter_key(it
), 0);
3922 if (hi
->announcements
!= '?') {
3923 flags
[0] = hi
->announcements
;
3925 saxdb_write_string(ctx
, KEY_ANNOUNCEMENTS
, flags
);
3928 struct handle_cookie
*cookie
= hi
->cookie
;
3931 switch (cookie
->type
) {
3932 case ACTIVATION
: type
= KEY_ACTIVATION
; break;
3933 case PASSWORD_CHANGE
: type
= KEY_PASSWORD_CHANGE
; break;
3934 case EMAIL_CHANGE
: type
= KEY_EMAIL_CHANGE
; break;
3935 case ALLOWAUTH
: type
= KEY_ALLOWAUTH
; break;
3936 default: type
= NULL
; break;
3939 saxdb_start_record(ctx
, KEY_COOKIE
, 0);
3940 saxdb_write_string(ctx
, KEY_COOKIE_TYPE
, type
);
3941 saxdb_write_int(ctx
, KEY_COOKIE_EXPIRES
, cookie
->expires
);
3943 saxdb_write_string(ctx
, KEY_COOKIE_DATA
, cookie
->data
);
3944 saxdb_write_string(ctx
, KEY_COOKIE
, cookie
->cookie
);
3945 saxdb_end_record(ctx
);
3949 saxdb_write_string(ctx
, KEY_EMAIL_ADDR
, hi
->email_addr
);
3951 saxdb_write_string(ctx
, KEY_EPITHET
, hi
->epithet
);
3953 saxdb_start_record(ctx
, KEY_NOTE_NOTE
, 0);
3954 saxdb_write_string(ctx
, KEY_NOTE_SETTER
, hi
->note
->setter
);
3955 saxdb_write_int(ctx
, KEY_NOTE_DATE
, hi
->note
->date
);
3956 saxdb_write_string(ctx
, KEY_NOTE_NOTE
, hi
->note
->note
);
3957 saxdb_end_record(ctx
);
3961 saxdb_write_string(ctx
, KEY_FAKEHOST
, hi
->fakehost
);
3965 for (ii
=flen
=0; handle_flags
[ii
]; ++ii
)
3966 if (hi
->flags
& (1 << ii
))
3967 flags
[flen
++] = handle_flags
[ii
];
3969 saxdb_write_string(ctx
, KEY_FLAGS
, flags
);
3972 saxdb_write_string(ctx
, KEY_INFO
, hi
->infoline
);
3973 if (hi
->last_quit_host
[0])
3974 saxdb_write_string(ctx
, KEY_LAST_QUIT_HOST
, hi
->last_quit_host
);
3975 saxdb_write_int(ctx
, KEY_LAST_SEEN
, hi
->lastseen
);
3977 saxdb_write_sint(ctx
, KEY_KARMA
, hi
->karma
);
3978 if (hi
->masks
->used
)
3979 saxdb_write_string_list(ctx
, KEY_MASKS
, hi
->masks
);
3980 if (hi
->sslfps
->used
)
3981 saxdb_write_string_list(ctx
, KEY_SSLFPS
, hi
->sslfps
);
3982 if (hi
->ignores
->used
)
3983 saxdb_write_string_list(ctx
, KEY_IGNORES
, hi
->ignores
);
3985 saxdb_write_int(ctx
, KEY_MAXLOGINS
, hi
->maxlogins
);
3987 struct string_list
*slist
;
3988 struct nick_info
*ni
;
3990 slist
= alloc_string_list(nickserv_conf
.nicks_per_handle
);
3991 for (ni
= hi
->nicks
; ni
; ni
= ni
->next
) string_list_append(slist
, ni
->nick
);
3992 saxdb_write_string_list(ctx
, KEY_NICKS
, slist
);
3996 if (hi
->opserv_level
)
3997 saxdb_write_int(ctx
, KEY_OPSERV_LEVEL
, hi
->opserv_level
);
3998 if (hi
->language
!= lang_C
)
3999 saxdb_write_string(ctx
, KEY_LANGUAGE
, hi
->language
->name
);
4000 saxdb_write_string(ctx
, KEY_PASSWD
, hi
->passwd
);
4001 saxdb_write_int(ctx
, KEY_REGISTER_ON
, hi
->registered
);
4002 if (hi
->screen_width
)
4003 saxdb_write_int(ctx
, KEY_SCREEN_WIDTH
, hi
->screen_width
);
4004 if (hi
->table_width
)
4005 saxdb_write_int(ctx
, KEY_TABLE_WIDTH
, hi
->table_width
);
4006 flags
[0] = hi
->userlist_style
;
4008 saxdb_write_string(ctx
, KEY_USERLIST_STYLE
, flags
);
4009 saxdb_end_record(ctx
);
4015 static handle_merge_func_t
*handle_merge_func_list
;
4016 static void **handle_merge_func_list_extra
;
4017 static unsigned int handle_merge_func_size
= 0, handle_merge_func_used
= 0;
4020 reg_handle_merge_func(handle_merge_func_t func
, void *extra
)
4022 if (handle_merge_func_used
== handle_merge_func_size
) {
4023 if (handle_merge_func_size
) {
4024 handle_merge_func_size
<<= 1;
4025 handle_merge_func_list
= realloc(handle_merge_func_list
, handle_merge_func_size
*sizeof(handle_merge_func_t
));
4026 handle_merge_func_list_extra
= realloc(handle_merge_func_list_extra
, handle_merge_func_size
*sizeof(void*));
4028 handle_merge_func_size
= 8;
4029 handle_merge_func_list
= malloc(handle_merge_func_size
*sizeof(handle_merge_func_t
));
4030 handle_merge_func_list_extra
= malloc(handle_merge_func_size
*sizeof(void*));
4033 handle_merge_func_list
[handle_merge_func_used
] = func
;
4034 handle_merge_func_list_extra
[handle_merge_func_used
++] = extra
;
4037 static NICKSERV_FUNC(cmd_merge
)
4039 struct handle_info
*hi_from
, *hi_to
;
4040 struct userNode
*last_user
;
4041 struct userData
*cList
, *cListNext
;
4042 unsigned int ii
, jj
, n
;
4044 NICKSERV_MIN_PARMS(3);
4046 if (!(hi_from
= get_victim_oper(user
, argv
[1])))
4048 if (!(hi_to
= get_victim_oper(user
, argv
[2])))
4050 if (hi_to
== hi_from
) {
4051 reply("NSMSG_CANNOT_MERGE_SELF", hi_to
->handle
);
4055 for (n
=0; n
<handle_merge_func_used
; n
++)
4056 handle_merge_func_list
[n
](user
, hi_to
, hi_from
, handle_merge_func_list_extra
[n
]);
4058 /* Append "from" handle's nicks to "to" handle's nick list. */
4060 struct nick_info
*last_ni
;
4061 for (last_ni
=hi_to
->nicks
; last_ni
->next
; last_ni
=last_ni
->next
) ;
4062 last_ni
->next
= hi_from
->nicks
;
4064 while (hi_from
->nicks
) {
4065 hi_from
->nicks
->owner
= hi_to
;
4066 hi_from
->nicks
= hi_from
->nicks
->next
;
4069 /* Merge the hostmasks. */
4070 for (ii
=0; ii
<hi_from
->masks
->used
; ii
++) {
4071 char *mask
= hi_from
->masks
->list
[ii
];
4072 for (jj
=0; jj
<hi_to
->masks
->used
; jj
++)
4073 if (match_ircglobs(hi_to
->masks
->list
[jj
], mask
))
4075 if (jj
==hi_to
->masks
->used
) /* Nothing from the "to" handle covered this mask, so add it. */
4076 string_list_append(hi_to
->masks
, strdup(mask
));
4079 /* Merge the SSL fingerprints. */
4080 for (ii
=0; ii
<hi_from
->sslfps
->used
; ii
++) {
4081 char *sslfp
= hi_from
->sslfps
->list
[ii
];
4082 for (jj
=0; jj
<hi_to
->sslfps
->used
; jj
++)
4083 if (!irccasecmp(hi_to
->sslfps
->list
[jj
], sslfp
))
4085 if (jj
==hi_to
->sslfps
->used
) /* Nothing from the "to" handle covered this sslfp, so add it. */
4086 string_list_append(hi_to
->sslfps
, strdup(sslfp
));
4089 /* Merge the ignores. */
4090 for (ii
=0; ii
<hi_from
->ignores
->used
; ii
++) {
4091 char *ignore
= hi_from
->ignores
->list
[ii
];
4092 for (jj
=0; jj
<hi_to
->ignores
->used
; jj
++)
4093 if (match_ircglobs(hi_to
->ignores
->list
[jj
], ignore
))
4095 if (jj
==hi_to
->ignores
->used
) /* Nothing from the "to" handle covered this mask, so add it. */
4096 string_list_append(hi_to
->ignores
, strdup(ignore
));
4099 /* Merge the lists of authed users. */
4101 for (last_user
=hi_to
->users
; last_user
->next_authed
; last_user
=last_user
->next_authed
) ;
4102 last_user
->next_authed
= hi_from
->users
;
4104 hi_to
->users
= hi_from
->users
;
4106 /* Repoint the old "from" handle's users. */
4107 for (last_user
=hi_from
->users
; last_user
; last_user
=last_user
->next_authed
) {
4108 last_user
->handle_info
= hi_to
;
4110 hi_from
->users
= NULL
;
4112 /* Merge channel userlists. */
4113 for (cList
=hi_from
->channels
; cList
; cList
=cListNext
) {
4114 struct userData
*cList2
;
4115 cListNext
= cList
->u_next
;
4116 for (cList2
=hi_to
->channels
; cList2
; cList2
=cList2
->u_next
)
4117 if (cList
->channel
== cList2
->channel
)
4119 if (cList2
&& (cList2
->access
>= cList
->access
)) {
4120 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
);
4121 /* keep cList2 in hi_to; remove cList from hi_from */
4122 del_channel_user(cList
, 1);
4125 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
);
4126 /* remove the lower-ranking cList2 from hi_to */
4127 del_channel_user(cList2
, 1);
4129 log_module(NS_LOG
, LOG_INFO
, "Merge: %s had no access in %s", hi_to
->handle
, cList
->channel
->channel
->name
);
4131 /* cList needs to be moved from hi_from to hi_to */
4132 cList
->handle
= hi_to
;
4133 /* Remove from linked list for hi_from */
4134 assert(!cList
->u_prev
);
4135 hi_from
->channels
= cList
->u_next
;
4137 cList
->u_next
->u_prev
= cList
->u_prev
;
4138 /* Add to linked list for hi_to */
4139 cList
->u_prev
= NULL
;
4140 cList
->u_next
= hi_to
->channels
;
4141 if (hi_to
->channels
)
4142 hi_to
->channels
->u_prev
= cList
;
4143 hi_to
->channels
= cList
;
4147 /* Do they get an OpServ level promotion? */
4148 if (hi_from
->opserv_level
> hi_to
->opserv_level
)
4149 hi_to
->opserv_level
= hi_from
->opserv_level
;
4151 /* What about last seen time? */
4152 if (hi_from
->lastseen
> hi_to
->lastseen
)
4153 hi_to
->lastseen
= hi_from
->lastseen
;
4155 /* New karma is the sum of the two original karmas. */
4156 hi_to
->karma
+= hi_from
->karma
;
4158 /* Does a fakehost carry over? (This intentionally doesn't set it
4159 * for users previously attached to hi_to. They'll just have to
4162 if (hi_from
->fakehost
&& !hi_to
->fakehost
)
4163 hi_to
->fakehost
= strdup(hi_from
->fakehost
);
4165 /* Notify of success. */
4166 reply("NSMSG_HANDLES_MERGED", hi_from
->handle
, hi_to
->handle
);
4167 global_message_args(MESSAGE_RECIPIENT_OPERS
, "NSMSG_ACCOUNT_MERGED", user
->nick
,
4168 user
->handle_info
->handle
, hi_from
->handle
, hi_to
->handle
);
4170 /* Unregister the "from" handle. */
4171 nickserv_unregister_handle(hi_from
, NULL
, cmd
->parent
->bot
);
4172 /* TODO: fix it so that if the ldap delete in nickserv_unregister_handle fails,
4173 * the process isn't completed.
4179 struct nickserv_discrim
{
4180 unsigned long flags_on
, flags_off
;
4181 time_t min_registered
, max_registered
;
4184 int min_level
, max_level
;
4185 int min_karma
, max_karma
;
4186 enum { SUBSET
, EXACT
, SUPERSET
, LASTQUIT
} hostmask_type
;
4187 const char *nickmask
;
4188 const char *hostmask
;
4189 const char *handlemask
;
4190 const char *emailmask
;
4192 unsigned int inldap
;
4196 typedef void (*discrim_search_func
)(struct userNode
*source
, struct handle_info
*hi
);
4198 struct discrim_apply_info
{
4199 struct nickserv_discrim
*discrim
;
4200 discrim_search_func func
;
4201 struct userNode
*source
;
4202 unsigned int matched
;
4205 static struct nickserv_discrim
*
4206 nickserv_discrim_create(struct svccmd
*cmd
, struct userNode
*user
, unsigned int argc
, char *argv
[])
4209 struct nickserv_discrim
*discrim
;
4211 discrim
= malloc(sizeof(*discrim
));
4212 memset(discrim
, 0, sizeof(*discrim
));
4213 discrim
->min_level
= 0;
4214 discrim
->max_level
= INT_MAX
;
4215 discrim
->limit
= 50;
4216 discrim
->min_registered
= 0;
4217 discrim
->max_registered
= INT_MAX
;
4218 discrim
->lastseen
= LONG_MAX
;
4219 discrim
->min_karma
= INT_MIN
;
4220 discrim
->max_karma
= INT_MAX
;
4222 discrim
->inldap
= 2;
4225 for (i
=0; i
<argc
; i
++) {
4226 if (i
== argc
- 1) {
4227 reply("MSG_MISSING_PARAMS", argv
[i
]);
4230 if (!irccasecmp(argv
[i
], "limit")) {
4231 discrim
->limit
= strtoul(argv
[++i
], NULL
, 0);
4232 } else if (!irccasecmp(argv
[i
], "flags")) {
4233 nickserv_modify_handle_flags(user
, nickserv
, argv
[++i
], &discrim
->flags_on
, &discrim
->flags_off
);
4234 } else if (!irccasecmp(argv
[i
], "registered")) {
4235 const char *cmp
= argv
[++i
];
4236 if (cmp
[0] == '<') {
4237 if (cmp
[1] == '=') {
4238 discrim
->min_registered
= now
- ParseInterval(cmp
+2);
4240 discrim
->min_registered
= now
- ParseInterval(cmp
+1) + 1;
4242 } else if (cmp
[0] == '=') {
4243 discrim
->min_registered
= discrim
->max_registered
= now
- ParseInterval(cmp
+1);
4244 } else if (cmp
[0] == '>') {
4245 if (cmp
[1] == '=') {
4246 discrim
->max_registered
= now
- ParseInterval(cmp
+2);
4248 discrim
->max_registered
= now
- ParseInterval(cmp
+1) - 1;
4251 reply("MSG_INVALID_CRITERIA", cmp
);
4253 } else if (!irccasecmp(argv
[i
], "seen")) {
4254 discrim
->lastseen
= now
- ParseInterval(argv
[++i
]);
4255 } else if (!nickserv_conf
.disable_nicks
&& !irccasecmp(argv
[i
], "nickmask")) {
4256 discrim
->nickmask
= argv
[++i
];
4257 } else if (!irccasecmp(argv
[i
], "hostmask")) {
4259 if (!irccasecmp(argv
[i
], "exact")) {
4260 if (i
== argc
- 1) {
4261 reply("MSG_MISSING_PARAMS", argv
[i
]);
4264 discrim
->hostmask_type
= EXACT
;
4265 } else if (!irccasecmp(argv
[i
], "subset")) {
4266 if (i
== argc
- 1) {
4267 reply("MSG_MISSING_PARAMS", argv
[i
]);
4270 discrim
->hostmask_type
= SUBSET
;
4271 } else if (!irccasecmp(argv
[i
], "superset")) {
4272 if (i
== argc
- 1) {
4273 reply("MSG_MISSING_PARAMS", argv
[i
]);
4276 discrim
->hostmask_type
= SUPERSET
;
4277 } else if (!irccasecmp(argv
[i
], "lastquit") || !irccasecmp(argv
[i
], "lastauth")) {
4278 if (i
== argc
- 1) {
4279 reply("MSG_MISSING_PARAMS", argv
[i
]);
4282 discrim
->hostmask_type
= LASTQUIT
;
4285 discrim
->hostmask_type
= SUPERSET
;
4287 discrim
->hostmask
= argv
[++i
];
4288 } else if (!irccasecmp(argv
[i
], "handlemask") || !irccasecmp(argv
[i
], "accountmask") || !irccasecmp(argv
[i
], "account")) {
4289 if (!irccasecmp(argv
[++i
], "*")) {
4290 discrim
->handlemask
= 0;
4292 discrim
->handlemask
= argv
[i
];
4294 } else if (!irccasecmp(argv
[i
], "email")) {
4295 if (user
->handle_info
->opserv_level
< nickserv_conf
.email_search_level
) {
4296 reply("MSG_NO_SEARCH_ACCESS", "email");
4298 } else if (!irccasecmp(argv
[++i
], "*")) {
4299 discrim
->emailmask
= 0;
4301 discrim
->emailmask
= argv
[i
];
4303 } else if (!irccasecmp(argv
[i
], "access")) {
4304 const char *cmp
= argv
[++i
];
4305 if (cmp
[0] == '<') {
4306 if (discrim
->min_level
== 0) discrim
->min_level
= 1;
4307 if (cmp
[1] == '=') {
4308 discrim
->max_level
= strtoul(cmp
+2, NULL
, 0);
4310 discrim
->max_level
= strtoul(cmp
+1, NULL
, 0) - 1;
4312 } else if (cmp
[0] == '=') {
4313 discrim
->min_level
= discrim
->max_level
= strtoul(cmp
+1, NULL
, 0);
4314 } else if (cmp
[0] == '>') {
4315 if (cmp
[1] == '=') {
4316 discrim
->min_level
= strtoul(cmp
+2, NULL
, 0);
4318 discrim
->min_level
= strtoul(cmp
+1, NULL
, 0) + 1;
4321 reply("MSG_INVALID_CRITERIA", cmp
);
4323 } else if (!irccasecmp(argv
[i
], "karma")) {
4324 const char *cmp
= argv
[++i
];
4325 if (cmp
[0] == '<') {
4326 if (cmp
[1] == '=') {
4327 discrim
->max_karma
= strtoul(cmp
+2, NULL
, 0);
4329 discrim
->max_karma
= strtoul(cmp
+1, NULL
, 0) - 1;
4331 } else if (cmp
[0] == '=') {
4332 discrim
->min_karma
= discrim
->max_karma
= strtoul(cmp
+1, NULL
, 0);
4333 } else if (cmp
[0] == '>') {
4334 if (cmp
[1] == '=') {
4335 discrim
->min_karma
= strtoul(cmp
+2, NULL
, 0);
4337 discrim
->min_karma
= strtoul(cmp
+1, NULL
, 0) + 1;
4340 send_message(user
, nickserv
, "MSG_INVALID_CRITERIA", cmp
);
4343 } else if (nickserv_conf
.ldap_enable
&& !irccasecmp(argv
[i
], "inldap")) {
4345 if(true_string(argv
[i
])) {
4346 discrim
->inldap
= 1;
4348 else if (false_string(argv
[i
])) {
4349 discrim
->inldap
= 0;
4352 reply("MSG_INVALID_BINARY", argv
[i
]);
4356 reply("MSG_INVALID_CRITERIA", argv
[i
]);
4367 nickserv_discrim_match(struct nickserv_discrim
*discrim
, struct handle_info
*hi
)
4369 if (((discrim
->flags_on
& hi
->flags
) != discrim
->flags_on
)
4370 || (discrim
->flags_off
& hi
->flags
)
4371 || (discrim
->min_registered
> hi
->registered
)
4372 || (discrim
->max_registered
< hi
->registered
)
4373 || (discrim
->lastseen
< (hi
->users
?now
:hi
->lastseen
))
4374 || (discrim
->handlemask
&& !match_ircglob(hi
->handle
, discrim
->handlemask
))
4375 || (discrim
->emailmask
&& (!hi
->email_addr
|| !match_ircglob(hi
->email_addr
, discrim
->emailmask
)))
4376 || (discrim
->min_level
> hi
->opserv_level
)
4377 || (discrim
->max_level
< hi
->opserv_level
)
4378 || (discrim
->min_karma
> hi
->karma
)
4379 || (discrim
->max_karma
< hi
->karma
)
4383 if (discrim
->hostmask
) {
4385 for (i
=0; i
<hi
->masks
->used
; i
++) {
4386 const char *mask
= hi
->masks
->list
[i
];
4387 if ((discrim
->hostmask_type
== SUBSET
)
4388 && (match_ircglobs(discrim
->hostmask
, mask
))) break;
4389 else if ((discrim
->hostmask_type
== EXACT
)
4390 && !irccasecmp(discrim
->hostmask
, mask
)) break;
4391 else if ((discrim
->hostmask_type
== SUPERSET
)
4392 && (match_ircglobs(mask
, discrim
->hostmask
))) break;
4393 else if ((discrim
->hostmask_type
== LASTQUIT
)
4394 && (match_ircglobs(discrim
->hostmask
, hi
->last_quit_host
))) break;
4396 if (i
==hi
->masks
->used
) return 0;
4398 if (discrim
->nickmask
) {
4399 struct nick_info
*nick
= hi
->nicks
;
4401 if (match_ircglob(nick
->nick
, discrim
->nickmask
)) break;
4404 if (!nick
) return 0;
4407 if(nickserv_conf
.ldap_enable
&& discrim
->inldap
!= 2) {
4409 rc
= ldap_get_user_info(hi
->handle
, NULL
);
4410 if(discrim
->inldap
== 1 && rc
!= LDAP_SUCCESS
)
4412 if(discrim
->inldap
== 0 && rc
== LDAP_SUCCESS
)
4421 nickserv_discrim_search(struct nickserv_discrim
*discrim
, discrim_search_func dsf
, struct userNode
*source
)
4423 dict_iterator_t it
, next
;
4424 unsigned int matched
;
4426 for (it
= dict_first(nickserv_handle_dict
), matched
= 0;
4427 it
&& (matched
< discrim
->limit
);
4429 next
= iter_next(it
);
4430 if (nickserv_discrim_match(discrim
, iter_data(it
))) {
4431 dsf(source
, iter_data(it
));
4439 search_print_func(struct userNode
*source
, struct handle_info
*match
)
4441 send_message(source
, nickserv
, "NSMSG_SEARCH_MATCH", match
->handle
);
4445 search_count_func(UNUSED_ARG(struct userNode
*source
), UNUSED_ARG(struct handle_info
*match
))
4450 search_unregister_func (struct userNode
*source
, struct handle_info
*match
)
4452 if (oper_has_access(source
, nickserv
, match
->opserv_level
, 0))
4453 nickserv_unregister_handle(match
, source
, nickserv
); // XXX nickserv hard coded
4458 search_add2ldap_func (struct userNode
*source
, struct handle_info
*match
)
4461 if(match
->email_addr
&& match
->passwd
&& match
->handle
) {
4462 rc
= ldap_do_add(match
->handle
, match
->passwd
, match
->email_addr
);
4463 if(rc
!= LDAP_SUCCESS
) {
4464 send_message(source
, nickserv
, "NSMSG_LDAP_FAIL_ADD", match
->handle
, ldap_err2string(rc
));
4471 nickserv_sort_accounts_by_access(const void *a
, const void *b
)
4473 const struct handle_info
*hi_a
= *(const struct handle_info
**)a
;
4474 const struct handle_info
*hi_b
= *(const struct handle_info
**)b
;
4475 if (hi_a
->opserv_level
!= hi_b
->opserv_level
)
4476 return hi_b
->opserv_level
- hi_a
->opserv_level
;
4477 return irccasecmp(hi_a
->handle
, hi_b
->handle
);
4481 nickserv_show_oper_accounts(struct userNode
*user
, struct svccmd
*cmd
)
4483 struct handle_info_list hil
;
4484 struct helpfile_table tbl
;
4489 memset(&hil
, 0, sizeof(hil
));
4490 for (it
= dict_first(nickserv_handle_dict
); it
; it
= iter_next(it
)) {
4491 struct handle_info
*hi
= iter_data(it
);
4492 if (hi
->opserv_level
)
4493 handle_info_list_append(&hil
, hi
);
4495 qsort(hil
.list
, hil
.used
, sizeof(hil
.list
[0]), nickserv_sort_accounts_by_access
);
4496 tbl
.length
= hil
.used
+ 1;
4498 tbl
.flags
= TABLE_NO_FREE
| TABLE_REPEAT_ROWS
| TABLE_REPEAT_HEADERS
;
4499 tbl
.contents
= malloc(tbl
.length
* sizeof(tbl
.contents
[0]));
4500 tbl
.contents
[0] = ary
= malloc(tbl
.width
* sizeof(ary
[0]));
4503 for (ii
= 0; ii
< hil
.used
; ) {
4504 ary
= malloc(tbl
.width
* sizeof(ary
[0]));
4505 ary
[0] = hil
.list
[ii
]->handle
;
4506 ary
[1] = strtab(hil
.list
[ii
]->opserv_level
);
4507 tbl
.contents
[++ii
] = ary
;
4509 table_send(cmd
->parent
->bot
, user
->nick
, 0, NULL
, tbl
);
4510 /*reply("MSG_MATCH_COUNT", hil.used); */
4511 for (ii
= 0; ii
< hil
.used
; ii
++)
4512 free(tbl
.contents
[ii
]);
4517 static NICKSERV_FUNC(cmd_search
)
4519 struct nickserv_discrim
*discrim
;
4520 discrim_search_func action
;
4521 struct svccmd
*subcmd
;
4522 unsigned int matches
;
4525 NICKSERV_MIN_PARMS(3);
4526 sprintf(buf
, "search %s", argv
[1]);
4527 subcmd
= dict_find(nickserv_service
->commands
, buf
, NULL
);
4528 if (!irccasecmp(argv
[1], "print"))
4529 action
= search_print_func
;
4530 else if (!irccasecmp(argv
[1], "count"))
4531 action
= search_count_func
;
4532 else if (!irccasecmp(argv
[1], "unregister"))
4533 action
= search_unregister_func
;
4535 else if (nickserv_conf
.ldap_enable
&& !irccasecmp(argv
[1], "add2ldap"))
4536 action
= search_add2ldap_func
;
4539 reply("NSMSG_INVALID_ACTION", argv
[1]);
4543 if (subcmd
&& !svccmd_can_invoke(user
, nickserv
, subcmd
, NULL
, SVCCMD_NOISY
))
4546 discrim
= nickserv_discrim_create(cmd
, user
, argc
-2, argv
+2);
4550 if (action
== search_print_func
)
4551 reply("NSMSG_ACCOUNT_SEARCH_RESULTS");
4552 else if (action
== search_count_func
)
4553 discrim
->limit
= INT_MAX
;
4555 matches
= nickserv_discrim_search(discrim
, action
, user
);
4558 reply("MSG_MATCH_COUNT", matches
);
4560 reply("MSG_NO_MATCHES");
4566 static MODCMD_FUNC(cmd_checkpass
)
4568 struct handle_info
*hi
;
4570 NICKSERV_MIN_PARMS(3);
4571 if (!(hi
= get_handle_info(argv
[1]))) {
4572 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
4575 if (checkpass(argv
[2], hi
->passwd
))
4576 reply("CHECKPASS_YES");
4578 reply("CHECKPASS_NO");
4583 static MODCMD_FUNC(cmd_checkemail
)
4585 struct handle_info
*hi
;
4587 NICKSERV_MIN_PARMS(3);
4588 if (!(hi
= modcmd_get_handle_info(user
, argv
[1]))) {
4591 if (!hi
->email_addr
)
4592 reply("CHECKEMAIL_NOT_SET");
4593 else if (!irccasecmp(argv
[2], hi
->email_addr
))
4594 reply("CHECKEMAIL_YES");
4596 reply("CHECKEMAIL_NO");
4601 nickserv_db_read_handle(char *handle
, dict_t obj
)
4604 struct string_list
*masks
, *sslfps
, *slist
, *ignores
;
4605 struct handle_info
*hi
;
4606 struct userNode
*authed_users
;
4607 struct userData
*channel_list
;
4608 unsigned long int id
;
4611 char *setter
, *note
;
4614 str
= database_get_data(obj
, KEY_ID
, RECDB_QSTRING
);
4615 id
= str
? strtoul(str
, NULL
, 0) : 0;
4616 str
= database_get_data(obj
, KEY_PASSWD
, RECDB_QSTRING
);
4618 log_module(NS_LOG
, LOG_WARNING
, "did not find a password for %s -- skipping user.", handle
);
4621 if ((hi
= get_handle_info(handle
))) {
4622 authed_users
= hi
->users
;
4623 channel_list
= hi
->channels
;
4625 hi
->channels
= NULL
;
4626 dict_remove(nickserv_handle_dict
, hi
->handle
);
4628 authed_users
= NULL
;
4629 channel_list
= NULL
;
4631 if(nickserv_conf
.force_handles_lowercase
)
4632 irc_strtolower(handle
);
4633 hi
= register_handle(handle
, str
, id
);
4635 hi
->users
= authed_users
;
4636 while (authed_users
) {
4637 authed_users
->handle_info
= hi
;
4638 authed_users
= authed_users
->next_authed
;
4641 hi
->channels
= channel_list
;
4642 masks
= database_get_data(obj
, KEY_MASKS
, RECDB_STRING_LIST
);
4643 hi
->masks
= masks
? string_list_copy(masks
) : alloc_string_list(1);
4644 sslfps
= database_get_data(obj
, KEY_SSLFPS
, RECDB_STRING_LIST
);
4645 hi
->sslfps
= sslfps
? string_list_copy(sslfps
) : alloc_string_list(1);
4646 ignores
= database_get_data(obj
, KEY_IGNORES
, RECDB_STRING_LIST
);
4647 hi
->ignores
= ignores
? string_list_copy(ignores
) : alloc_string_list(1);
4648 str
= database_get_data(obj
, KEY_MAXLOGINS
, RECDB_QSTRING
);
4649 hi
->maxlogins
= str
? strtoul(str
, NULL
, 0) : 0;
4650 str
= database_get_data(obj
, KEY_LANGUAGE
, RECDB_QSTRING
);
4651 hi
->language
= language_find(str
? str
: "C");
4652 str
= database_get_data(obj
, KEY_OPSERV_LEVEL
, RECDB_QSTRING
);
4653 hi
->opserv_level
= str
? strtoul(str
, NULL
, 0) : 0;
4654 str
= database_get_data(obj
, KEY_INFO
, RECDB_QSTRING
);
4656 hi
->infoline
= strdup(str
);
4657 str
= database_get_data(obj
, KEY_REGISTER_ON
, RECDB_QSTRING
);
4658 hi
->registered
= str
? (time_t)strtoul(str
, NULL
, 0) : now
;
4659 str
= database_get_data(obj
, KEY_LAST_SEEN
, RECDB_QSTRING
);
4660 hi
->lastseen
= str
? (time_t)strtoul(str
, NULL
, 0) : hi
->registered
;
4661 str
= database_get_data(obj
, KEY_KARMA
, RECDB_QSTRING
);
4662 hi
->karma
= str
? strtoul(str
, NULL
, 0) : 0;
4663 /* We want to read the nicks even if disable_nicks is set. This is so
4664 * that we don't lose the nick data entirely. */
4665 slist
= database_get_data(obj
, KEY_NICKS
, RECDB_STRING_LIST
);
4667 for (ii
=0; ii
<slist
->used
; ii
++)
4668 register_nick(slist
->list
[ii
], hi
);
4670 str
= database_get_data(obj
, KEY_FLAGS
, RECDB_QSTRING
);
4672 for (ii
=0; str
[ii
]; ii
++)
4673 hi
->flags
|= 1 << (handle_inverse_flags
[(unsigned char)str
[ii
]] - 1);
4675 str
= database_get_data(obj
, KEY_USERLIST_STYLE
, RECDB_QSTRING
);
4676 hi
->userlist_style
= str
? str
[0] : HI_DEFAULT_STYLE
;
4677 str
= database_get_data(obj
, KEY_ANNOUNCEMENTS
, RECDB_QSTRING
);
4678 hi
->announcements
= str
? str
[0] : '?';
4679 str
= database_get_data(obj
, KEY_SCREEN_WIDTH
, RECDB_QSTRING
);
4680 hi
->screen_width
= str
? strtoul(str
, NULL
, 0) : 0;
4681 str
= database_get_data(obj
, KEY_TABLE_WIDTH
, RECDB_QSTRING
);
4682 hi
->table_width
= str
? strtoul(str
, NULL
, 0) : 0;
4683 str
= database_get_data(obj
, KEY_LAST_QUIT_HOST
, RECDB_QSTRING
);
4685 str
= database_get_data(obj
, KEY_LAST_AUTHED_HOST
, RECDB_QSTRING
);
4687 safestrncpy(hi
->last_quit_host
, str
, sizeof(hi
->last_quit_host
));
4688 str
= database_get_data(obj
, KEY_EMAIL_ADDR
, RECDB_QSTRING
);
4690 nickserv_set_email_addr(hi
, str
);
4691 str
= database_get_data(obj
, KEY_EPITHET
, RECDB_QSTRING
);
4693 hi
->epithet
= strdup(str
);
4694 subdb
= database_get_data(obj
, KEY_NOTE_NOTE
, RECDB_OBJECT
);
4696 setter
= database_get_data(subdb
, KEY_NOTE_SETTER
, RECDB_QSTRING
);
4697 str
= database_get_data(subdb
, KEY_NOTE_DATE
, RECDB_QSTRING
);
4698 date
= str
? (time_t)strtoul(str
, NULL
, 0) : now
;
4699 note
= database_get_data(subdb
, KEY_NOTE_NOTE
, RECDB_QSTRING
);
4700 if (setter
&& date
&& note
)
4702 if (!(hi
->note
= nickserv_add_note(setter
, date
, note
)))
4707 str
= database_get_data(obj
, KEY_FAKEHOST
, RECDB_QSTRING
);
4709 hi
->fakehost
= strdup(str
);
4711 subdb
= database_get_data(obj
, KEY_COOKIE
, RECDB_OBJECT
);
4713 const char *data
, *type
, *expires
, *cookie_str
;
4714 struct handle_cookie
*cookie
;
4716 cookie
= calloc(1, sizeof(*cookie
));
4717 type
= database_get_data(subdb
, KEY_COOKIE_TYPE
, RECDB_QSTRING
);
4718 data
= database_get_data(subdb
, KEY_COOKIE_DATA
, RECDB_QSTRING
);
4719 expires
= database_get_data(subdb
, KEY_COOKIE_EXPIRES
, RECDB_QSTRING
);
4720 cookie_str
= database_get_data(subdb
, KEY_COOKIE
, RECDB_QSTRING
);
4721 if (!type
|| !expires
|| !cookie_str
) {
4722 log_module(NS_LOG
, LOG_ERROR
, "Missing field(s) from cookie for account %s; dropping cookie.", hi
->handle
);
4725 if (!irccasecmp(type
, KEY_ACTIVATION
))
4726 cookie
->type
= ACTIVATION
;
4727 else if (!irccasecmp(type
, KEY_PASSWORD_CHANGE
))
4728 cookie
->type
= PASSWORD_CHANGE
;
4729 else if (!irccasecmp(type
, KEY_EMAIL_CHANGE
))
4730 cookie
->type
= EMAIL_CHANGE
;
4731 else if (!irccasecmp(type
, KEY_ALLOWAUTH
))
4732 cookie
->type
= ALLOWAUTH
;
4734 log_module(NS_LOG
, LOG_ERROR
, "Invalid cookie type %s for account %s; dropping cookie.", type
, handle
);
4737 cookie
->expires
= strtoul(expires
, NULL
, 0);
4738 if (cookie
->expires
< now
)
4741 cookie
->data
= strdup(data
);
4742 safestrncpy(cookie
->cookie
, cookie_str
, sizeof(cookie
->cookie
));
4746 nickserv_bake_cookie(cookie
);
4748 nickserv_free_cookie(cookie
);
4753 nickserv_saxdb_read(dict_t db
) {
4755 struct record_data
*rd
;
4758 for (it
=dict_first(db
); it
; it
=iter_next(it
)) {
4760 handle
= strdup(iter_key(it
));
4761 nickserv_db_read_handle(handle
, rd
->d
.object
);
4767 static NICKSERV_FUNC(cmd_mergedb
)
4769 struct timeval start
, stop
;
4772 NICKSERV_MIN_PARMS(2);
4773 gettimeofday(&start
, NULL
);
4774 if (!(db
= parse_database(argv
[1]))) {
4775 reply("NSMSG_DB_UNREADABLE", argv
[1]);
4778 nickserv_saxdb_read(db
);
4780 gettimeofday(&stop
, NULL
);
4781 stop
.tv_sec
-= start
.tv_sec
;
4782 stop
.tv_usec
-= start
.tv_usec
;
4783 if (stop
.tv_usec
< 0) {
4785 stop
.tv_usec
+= 1000000;
4787 reply("NSMSG_DB_MERGED", argv
[1], stop
.tv_sec
, stop
.tv_usec
/1000);
4792 expire_handles(UNUSED_ARG(void *data
))
4794 dict_iterator_t it
, next
;
4796 struct handle_info
*hi
;
4798 for (it
=dict_first(nickserv_handle_dict
); it
; it
=next
) {
4799 next
= iter_next(it
);
4801 if ((hi
->opserv_level
> 0)
4803 || HANDLE_FLAGGED(hi
, FROZEN
)
4804 || HANDLE_FLAGGED(hi
, NODELETE
)) {
4807 expiry
= hi
->channels
? nickserv_conf
.handle_expire_delay
: nickserv_conf
.nochan_handle_expire_delay
;
4808 if ((now
- hi
->lastseen
) > expiry
) {
4809 log_module(NS_LOG
, LOG_INFO
, "Expiring account %s for inactivity.", hi
->handle
);
4810 nickserv_unregister_handle(hi
, NULL
, NULL
);
4814 if (nickserv_conf
.handle_expire_frequency
)
4815 timeq_add(now
+ nickserv_conf
.handle_expire_frequency
, expire_handles
, NULL
);
4819 nickserv_load_dict(const char *fname
)
4823 if (!(file
= fopen(fname
, "r"))) {
4824 log_module(NS_LOG
, LOG_ERROR
, "Unable to open dictionary file %s: %s", fname
, strerror(errno
));
4827 while (fgets(line
, sizeof(line
), file
)) {
4830 if (line
[strlen(line
)-1] == '\n')
4831 line
[strlen(line
)-1] = 0;
4832 dict_insert(nickserv_conf
.weak_password_dict
, strdup(line
), NULL
);
4835 log_module(NS_LOG
, LOG_INFO
, "Loaded %d words into weak password dictionary.", dict_size(nickserv_conf
.weak_password_dict
));
4838 static enum reclaim_action
4839 reclaim_action_from_string(const char *str
) {
4841 return RECLAIM_NONE
;
4842 else if (!irccasecmp(str
, "warn"))
4843 return RECLAIM_WARN
;
4844 else if (!irccasecmp(str
, "svsnick"))
4845 return RECLAIM_SVSNICK
;
4846 else if (!irccasecmp(str
, "kill"))
4847 return RECLAIM_KILL
;
4849 return RECLAIM_NONE
;
4853 nickserv_conf_read(void)
4855 dict_t conf_node
, child
;
4858 struct string_list
*strlist
;
4860 if (!(conf_node
= conf_get_data(NICKSERV_CONF_NAME
, RECDB_OBJECT
))) {
4861 log_module(NS_LOG
, LOG_ERROR
, "config node `%s' is missing or has wrong type.", NICKSERV_CONF_NAME
);
4864 str
= database_get_data(conf_node
, KEY_VALID_HANDLE_REGEX
, RECDB_QSTRING
);
4866 str
= database_get_data(conf_node
, KEY_VALID_ACCOUNT_REGEX
, RECDB_QSTRING
);
4867 if (nickserv_conf
.valid_handle_regex_set
)
4868 regfree(&nickserv_conf
.valid_handle_regex
);
4870 int err
= regcomp(&nickserv_conf
.valid_handle_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
4871 nickserv_conf
.valid_handle_regex_set
= !err
;
4872 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_account_regex (error %d)", err
);
4874 nickserv_conf
.valid_handle_regex_set
= 0;
4876 str
= database_get_data(conf_node
, KEY_VALID_NICK_REGEX
, RECDB_QSTRING
);
4877 if (nickserv_conf
.valid_nick_regex_set
)
4878 regfree(&nickserv_conf
.valid_nick_regex
);
4880 int err
= regcomp(&nickserv_conf
.valid_nick_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
4881 nickserv_conf
.valid_nick_regex_set
= !err
;
4882 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_nick_regex (error %d)", err
);
4884 nickserv_conf
.valid_nick_regex_set
= 0;
4886 str
= database_get_data(conf_node
, KEY_VALID_FAKEHOST_REGEX
, RECDB_QSTRING
);
4887 if (nickserv_conf
.valid_fakehost_regex_set
)
4888 regfree(&nickserv_conf
.valid_fakehost_regex
);
4890 int err
= regcomp(&nickserv_conf
.valid_fakehost_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
4891 nickserv_conf
.valid_fakehost_regex_set
= !err
;
4892 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_fakehost_regex (error %d)", err
);
4894 nickserv_conf
.valid_fakehost_regex_set
= 0;
4896 str
= database_get_data(conf_node
, KEY_NICKS_PER_HANDLE
, RECDB_QSTRING
);
4898 str
= database_get_data(conf_node
, KEY_NICKS_PER_ACCOUNT
, RECDB_QSTRING
);
4899 nickserv_conf
.nicks_per_handle
= str
? strtoul(str
, NULL
, 0) : 4;
4900 str
= database_get_data(conf_node
, KEY_DISABLE_NICKS
, RECDB_QSTRING
);
4901 nickserv_conf
.disable_nicks
= str
? strtoul(str
, NULL
, 0) : 0;
4902 str
= database_get_data(conf_node
, KEY_DEFAULT_HOSTMASK
, RECDB_QSTRING
);
4903 nickserv_conf
.default_hostmask
= str
? !disabled_string(str
) : 0;
4904 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_LENGTH
, RECDB_QSTRING
);
4905 nickserv_conf
.password_min_length
= str
? strtoul(str
, NULL
, 0) : 0;
4906 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_DIGITS
, RECDB_QSTRING
);
4907 nickserv_conf
.password_min_digits
= str
? strtoul(str
, NULL
, 0) : 0;
4908 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_UPPER
, RECDB_QSTRING
);
4909 nickserv_conf
.password_min_upper
= str
? strtoul(str
, NULL
, 0) : 0;
4910 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_LOWER
, RECDB_QSTRING
);
4911 nickserv_conf
.password_min_lower
= str
? strtoul(str
, NULL
, 0) : 0;
4912 str
= database_get_data(conf_node
, KEY_DB_BACKUP_FREQ
, RECDB_QSTRING
);
4913 nickserv_conf
.db_backup_frequency
= str
? ParseInterval(str
) : 7200;
4914 str
= database_get_data(conf_node
, KEY_MODOPER_LEVEL
, RECDB_QSTRING
);
4915 nickserv_conf
.modoper_level
= str
? strtoul(str
, NULL
, 0) : 900;
4916 str
= database_get_data(conf_node
, KEY_SET_EPITHET_LEVEL
, RECDB_QSTRING
);
4917 nickserv_conf
.set_epithet_level
= str
? strtoul(str
, NULL
, 0) : 1;
4918 str
= database_get_data(conf_node
, KEY_SET_TITLE_LEVEL
, RECDB_QSTRING
);
4919 nickserv_conf
.set_title_level
= str
? strtoul(str
, NULL
, 0) : 900;
4920 str
= database_get_data(conf_node
, KEY_SET_FAKEHOST_LEVEL
, RECDB_QSTRING
);
4921 nickserv_conf
.set_fakehost_level
= str
? strtoul(str
, NULL
, 0) : 1000;
4922 str
= database_get_data(conf_node
, KEY_HANDLE_EXPIRE_FREQ
, RECDB_QSTRING
);
4924 str
= database_get_data(conf_node
, KEY_ACCOUNT_EXPIRE_FREQ
, RECDB_QSTRING
);
4925 nickserv_conf
.handle_expire_frequency
= str
? ParseInterval(str
) : 86400;
4926 str
= database_get_data(conf_node
, KEY_HANDLE_EXPIRE_DELAY
, RECDB_QSTRING
);
4928 str
= database_get_data(conf_node
, KEY_ACCOUNT_EXPIRE_DELAY
, RECDB_QSTRING
);
4929 nickserv_conf
.handle_expire_delay
= str
? ParseInterval(str
) : 86400*30;
4930 str
= database_get_data(conf_node
, KEY_NOCHAN_HANDLE_EXPIRE_DELAY
, RECDB_QSTRING
);
4932 str
= database_get_data(conf_node
, KEY_NOCHAN_ACCOUNT_EXPIRE_DELAY
, RECDB_QSTRING
);
4933 nickserv_conf
.nochan_handle_expire_delay
= str
? ParseInterval(str
) : 86400*15;
4934 str
= database_get_data(conf_node
, "warn_clone_auth", RECDB_QSTRING
);
4935 nickserv_conf
.warn_clone_auth
= str
? !disabled_string(str
) : 1;
4936 str
= database_get_data(conf_node
, "default_maxlogins", RECDB_QSTRING
);
4937 nickserv_conf
.default_maxlogins
= str
? strtoul(str
, NULL
, 0) : 2;
4938 str
= database_get_data(conf_node
, "hard_maxlogins", RECDB_QSTRING
);
4939 str
= database_get_data(conf_node
, KEY_OUNREGISTER_INACTIVE
, RECDB_QSTRING
);
4940 nickserv_conf
.ounregister_inactive
= str
? ParseInterval(str
) : 86400*28;
4941 str
= database_get_data(conf_node
, KEY_OUNREGISTER_FLAGS
, RECDB_QSTRING
);
4944 nickserv_conf
.ounregister_flags
= 0;
4946 unsigned int pos
= handle_inverse_flags
[(unsigned char)*str
];
4949 nickserv_conf
.ounregister_flags
|= 1 << (pos
- 1);
4951 nickserv_conf
.hard_maxlogins
= str
? strtoul(str
, NULL
, 0) : 10;
4952 if (!nickserv_conf
.disable_nicks
) {
4953 str
= database_get_data(conf_node
, "reclaim_action", RECDB_QSTRING
);
4954 nickserv_conf
.reclaim_action
= str
? reclaim_action_from_string(str
) : RECLAIM_NONE
;
4955 str
= database_get_data(conf_node
, "warn_nick_owned", RECDB_QSTRING
);
4956 nickserv_conf
.warn_nick_owned
= str
? enabled_string(str
) : 0;
4957 str
= database_get_data(conf_node
, "auto_reclaim_action", RECDB_QSTRING
);
4958 nickserv_conf
.auto_reclaim_action
= str
? reclaim_action_from_string(str
) : RECLAIM_NONE
;
4959 str
= database_get_data(conf_node
, "auto_reclaim_delay", RECDB_QSTRING
);
4960 nickserv_conf
.auto_reclaim_delay
= str
? ParseInterval(str
) : 0;
4962 child
= database_get_data(conf_node
, KEY_FLAG_LEVELS
, RECDB_OBJECT
);
4963 for (it
=dict_first(child
); it
; it
=iter_next(it
)) {
4964 const char *key
= iter_key(it
), *value
;
4968 if (!strncasecmp(key
, "uc_", 3))
4969 flag
= toupper(key
[3]);
4970 else if (!strncasecmp(key
, "lc_", 3))
4971 flag
= tolower(key
[3]);
4975 if ((pos
= handle_inverse_flags
[flag
])) {
4976 value
= GET_RECORD_QSTRING((struct record_data
*)iter_data(it
));
4977 flag_access_levels
[pos
- 1] = strtoul(value
, NULL
, 0);
4980 if (nickserv_conf
.weak_password_dict
)
4981 dict_delete(nickserv_conf
.weak_password_dict
);
4982 nickserv_conf
.weak_password_dict
= dict_new();
4983 dict_set_free_keys(nickserv_conf
.weak_password_dict
, free
);
4984 dict_insert(nickserv_conf
.weak_password_dict
, strdup("password"), NULL
);
4985 dict_insert(nickserv_conf
.weak_password_dict
, strdup("<password>"), NULL
);
4986 str
= database_get_data(conf_node
, KEY_DICT_FILE
, RECDB_QSTRING
);
4988 nickserv_load_dict(str
);
4989 str
= database_get_data(conf_node
, KEY_NICK
, RECDB_QSTRING
);
4990 if (nickserv
&& str
)
4991 NickChange(nickserv
, str
, 0);
4992 str
= database_get_data(conf_node
, KEY_AUTOGAG_ENABLED
, RECDB_QSTRING
);
4993 nickserv_conf
.autogag_enabled
= str
? strtoul(str
, NULL
, 0) : 1;
4994 str
= database_get_data(conf_node
, KEY_AUTOGAG_DURATION
, RECDB_QSTRING
);
4995 nickserv_conf
.autogag_duration
= str
? ParseInterval(str
) : 1800;
4996 str
= database_get_data(conf_node
, KEY_EMAIL_VISIBLE_LEVEL
, RECDB_QSTRING
);
4997 nickserv_conf
.email_visible_level
= str
? strtoul(str
, NULL
, 0) : 800;
4998 str
= database_get_data(conf_node
, KEY_EMAIL_ENABLED
, RECDB_QSTRING
);
4999 nickserv_conf
.email_enabled
= str
? enabled_string(str
) : 0;
5000 str
= database_get_data(conf_node
, KEY_SYNC_LOG
, RECDB_QSTRING
);
5001 nickserv_conf
.sync_log
= str
? enabled_string(str
) : 0;
5002 str
= database_get_data(conf_node
, KEY_COOKIE_TIMEOUT
, RECDB_QSTRING
);
5003 nickserv_conf
.cookie_timeout
= str
? ParseInterval(str
) : 24*3600;
5004 str
= database_get_data(conf_node
, KEY_EMAIL_REQUIRED
, RECDB_QSTRING
);
5005 nickserv_conf
.email_required
= (nickserv_conf
.email_enabled
&& str
) ? enabled_string(str
) : 0;
5006 str
= database_get_data(conf_node
, KEY_ACCOUNTS_PER_EMAIL
, RECDB_QSTRING
);
5007 nickserv_conf
.handles_per_email
= str
? strtoul(str
, NULL
, 0) : 1;
5008 str
= database_get_data(conf_node
, KEY_EMAIL_SEARCH_LEVEL
, RECDB_QSTRING
);
5009 nickserv_conf
.email_search_level
= str
? strtoul(str
, NULL
, 0) : 600;
5010 str
= database_get_data(conf_node
, KEY_TITLEHOST_SUFFIX
, RECDB_QSTRING
);
5011 nickserv_conf
.titlehost_suffix
= str
? str
: "example.net";
5013 free_string_list(nickserv_conf
.denied_fakehost_words
);
5014 strlist
= database_get_data(conf_node
, KEY_DENIED_FAKEHOST_WORDS
, RECDB_STRING_LIST
);
5016 strlist
= string_list_copy(strlist
);
5018 strlist
= alloc_string_list(4);
5019 string_list_append(strlist
, strdup("sex"));
5020 string_list_append(strlist
, strdup("fuck"));
5022 nickserv_conf
.denied_fakehost_words
= strlist
;
5024 str
= database_get_data(conf_node
, KEY_DEFAULT_STYLE
, RECDB_QSTRING
);
5025 nickserv_conf
.default_style
= str
? str
[0] : HI_DEFAULT_STYLE
;
5027 str
= database_get_data(conf_node
, KEY_AUTO_OPER
, RECDB_QSTRING
);
5028 nickserv_conf
.auto_oper
= str
? str
: "";
5030 str
= database_get_data(conf_node
, KEY_AUTO_ADMIN
, RECDB_QSTRING
);
5031 nickserv_conf
.auto_admin
= str
? str
: "";
5033 str
= database_get_data(conf_node
, KEY_AUTO_OPER_PRIVS
, RECDB_QSTRING
);
5034 nickserv_conf
.auto_oper_privs
= str
? str
: "";
5036 str
= database_get_data(conf_node
, KEY_AUTO_ADMIN_PRIVS
, RECDB_QSTRING
);
5037 nickserv_conf
.auto_admin_privs
= str
? str
: "";
5039 str
= conf_get_data("server/network", RECDB_QSTRING
);
5040 nickserv_conf
.network_name
= str
? str
: "some IRC network";
5041 if (!nickserv_conf
.auth_policer_params
) {
5042 nickserv_conf
.auth_policer_params
= policer_params_new();
5043 policer_params_set(nickserv_conf
.auth_policer_params
, "size", "5");
5044 policer_params_set(nickserv_conf
.auth_policer_params
, "drain-rate", "0.05");
5046 child
= database_get_data(conf_node
, KEY_AUTH_POLICER
, RECDB_OBJECT
);
5047 for (it
=dict_first(child
); it
; it
=iter_next(it
))
5048 set_policer_param(iter_key(it
), iter_data(it
), nickserv_conf
.auth_policer_params
);
5050 str
= database_get_data(conf_node
, KEY_LDAP_ENABLE
, RECDB_QSTRING
);
5051 nickserv_conf
.ldap_enable
= str
? strtoul(str
, NULL
, 0) : 0;
5053 str
= database_get_data(conf_node
, KEY_FORCE_HANDLES_LOWERCASE
, RECDB_QSTRING
);
5054 nickserv_conf
.force_handles_lowercase
= str
? strtol(str
, NULL
, 0) : 0;
5057 if(nickserv_conf
.ldap_enable
> 0) {
5058 /* ldap is enabled but not compiled in - error out */
5059 log_module(MAIN_LOG
, LOG_ERROR
, "ldap is enabled in config, but not compiled in!");
5060 nickserv_conf
.ldap_enable
= 0;
5066 str
= database_get_data(conf_node
, KEY_LDAP_URI
, RECDB_QSTRING
);
5067 nickserv_conf
.ldap_uri
= str
? str
: "";
5069 str
= database_get_data(conf_node
, KEY_LDAP_BASE
, RECDB_QSTRING
);
5070 nickserv_conf
.ldap_base
= str
? str
: "";
5072 str
= database_get_data(conf_node
, KEY_LDAP_DN_FMT
, RECDB_QSTRING
);
5073 nickserv_conf
.ldap_dn_fmt
= str
? str
: "";
5075 str
= database_get_data(conf_node
, KEY_LDAP_VERSION
, RECDB_QSTRING
);
5076 nickserv_conf
.ldap_version
= str
? strtoul(str
, NULL
, 0) : 3;
5078 str
= database_get_data(conf_node
, KEY_LDAP_AUTOCREATE
, RECDB_QSTRING
);
5079 nickserv_conf
.ldap_autocreate
= str
? strtoul(str
, NULL
, 0) : 0;
5081 str
= database_get_data(conf_node
, KEY_LDAP_TIMEOUT
, RECDB_QSTRING
);
5082 nickserv_conf
.ldap_timeout
= str
? strtoul(str
, NULL
, 0) : 5;
5084 str
= database_get_data(conf_node
, KEY_LDAP_ADMIN_DN
, RECDB_QSTRING
);
5085 nickserv_conf
.ldap_admin_dn
= str
? str
: "";
5087 str
= database_get_data(conf_node
, KEY_LDAP_ADMIN_PASS
, RECDB_QSTRING
);
5088 nickserv_conf
.ldap_admin_pass
= str
? str
: "";
5090 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_ACCOUNT
, RECDB_QSTRING
);
5091 nickserv_conf
.ldap_field_account
= str
? str
: "";
5093 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_PASSWORD
, RECDB_QSTRING
);
5094 nickserv_conf
.ldap_field_password
= str
? str
: "";
5096 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_EMAIL
, RECDB_QSTRING
);
5097 nickserv_conf
.ldap_field_email
= str
? str
: "";
5099 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_OSLEVEL
, RECDB_QSTRING
);
5100 nickserv_conf
.ldap_field_oslevel
= str
? str
: "";
5102 str
= database_get_data(conf_node
, KEY_LDAP_OPER_GROUP_DN
, RECDB_QSTRING
);
5103 nickserv_conf
.ldap_oper_group_dn
= str
? str
: "";
5105 str
= database_get_data(conf_node
, KEY_LDAP_OPER_GROUP_LEVEL
, RECDB_QSTRING
);
5106 nickserv_conf
.ldap_oper_group_level
= str
? strtoul(str
, NULL
, 0) : 99;
5108 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_GROUP_MEMBER
, RECDB_QSTRING
);
5109 nickserv_conf
.ldap_field_group_member
= str
? str
: "";
5111 free_string_list(nickserv_conf
.ldap_object_classes
);
5112 strlist
= database_get_data(conf_node
, KEY_LDAP_OBJECT_CLASSES
, RECDB_STRING_LIST
);
5114 strlist
= string_list_copy(strlist
);
5116 strlist
= alloc_string_list(4);
5117 string_list_append(strlist
, strdup("top"));
5119 nickserv_conf
.ldap_object_classes
= strlist
;
5126 nickserv_reclaim(struct userNode
*user
, struct nick_info
*ni
, enum reclaim_action action
) {
5128 char newnick
[NICKLEN
+1];
5137 send_message(user
, nickserv
, "NSMSG_RECLAIM_WARN", ni
->nick
, ni
->owner
->handle
);
5138 send_message(user
, nickserv
, "NSMSG_RECLAIM_HOWTO", ni
->owner
->handle
, nickserv
->nick
, self
->name
, ni
->owner
->handle
);
5140 case RECLAIM_SVSNICK
:
5142 snprintf(newnick
, sizeof(newnick
), "Guest%d", rand()%10000
);
5143 } while (GetUserH(newnick
));
5144 irc_svsnick(nickserv
, user
, newnick
);
5147 msg
= user_find_message(user
, "NSMSG_RECLAIM_KILL");
5148 DelUser(user
, nickserv
, 1, msg
);
5154 nickserv_reclaim_p(void *data
) {
5155 struct userNode
*user
= data
;
5156 struct nick_info
*ni
= get_nick_info(user
->nick
);
5158 nickserv_reclaim(user
, ni
, nickserv_conf
.auto_reclaim_action
);
5162 check_user_nick(struct userNode
*user
, UNUSED_ARG(void *extra
)) {
5163 struct nick_info
*ni
;
5164 user
->modes
&= ~FLAGS_REGNICK
;
5165 if (!(ni
= get_nick_info(user
->nick
)))
5167 if (user
->handle_info
== ni
->owner
) {
5168 user
->modes
|= FLAGS_REGNICK
;
5172 if (nickserv_conf
.warn_nick_owned
)
5173 send_message(user
, nickserv
, "NSMSG_RECLAIM_WARN", ni
->nick
, ni
->owner
->handle
);
5174 send_message(user
, nickserv
, "NSMSG_RECLAIM_HOWTO", ni
->owner
->handle
, nickserv
->nick
, self
->name
, ni
->owner
->handle
);
5175 if (nickserv_conf
.auto_reclaim_action
== RECLAIM_NONE
)
5177 if (nickserv_conf
.auto_reclaim_delay
)
5178 timeq_add(now
+ nickserv_conf
.auto_reclaim_delay
, nickserv_reclaim_p
, user
);
5180 nickserv_reclaim(user
, ni
, nickserv_conf
.auto_reclaim_action
);
5186 handle_account(struct userNode
*user
, const char *stamp
)
5188 struct handle_info
*hi
;
5191 #ifdef WITH_PROTOCOL_P10
5192 time_t timestamp
= 0;
5194 colon
= strchr(stamp
, ':');
5195 if(colon
&& colon
[1])
5198 timestamp
= atoi(colon
+1);
5200 hi
= dict_find(nickserv_handle_dict
, stamp
, NULL
);
5201 if(hi
&& timestamp
&& hi
->registered
!= timestamp
)
5203 log_module(MAIN_LOG
, LOG_WARNING
, "%s using account %s but timestamp does not match %s is not %s.", user
->nick
, stamp
, ctime(×tamp
),
5204 ctime(&hi
->registered
));
5208 hi
= dict_find(nickserv_id_dict
, stamp
, NULL
);
5209 log_module(MAIN_LOG
, LOG_WARNING
, "Using non-P10 code in accounts, not tested at all!");
5213 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
5216 set_user_handle_info(user
, hi
, 0);
5218 log_module(MAIN_LOG
, LOG_WARNING
, "%s had unknown account stamp %s.", user
->nick
, stamp
);
5223 handle_nick_change(struct userNode
*user
, const char *old_nick
, UNUSED_ARG(void *extra
))
5225 struct handle_info
*hi
;
5227 if ((hi
= dict_find(nickserv_allow_auth_dict
, old_nick
, 0))) {
5228 dict_remove(nickserv_allow_auth_dict
, old_nick
);
5229 dict_insert(nickserv_allow_auth_dict
, user
->nick
, hi
);
5231 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
5232 check_user_nick(user
, NULL
);
5236 nickserv_remove_user(struct userNode
*user
, UNUSED_ARG(struct userNode
*killer
), UNUSED_ARG(const char *why
), UNUSED_ARG(void *extra
))
5238 dict_remove(nickserv_allow_auth_dict
, user
->nick
);
5239 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
5240 set_user_handle_info(user
, NULL
, 0);
5243 static struct modcmd
*
5244 nickserv_define_func(const char *name
, modcmd_func_t func
, int min_level
, int must_auth
, int must_be_qualified
)
5246 if (min_level
> 0) {
5248 sprintf(buf
, "%u", min_level
);
5249 if (must_be_qualified
) {
5250 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "level", buf
, "flags", "+qualified,+loghostmask", NULL
);
5252 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "level", buf
, NULL
);
5254 } else if (min_level
== 0) {
5255 if (must_be_qualified
) {
5256 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+helping", NULL
);
5258 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+helping", NULL
);
5261 if (must_be_qualified
) {
5262 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+qualified,+loghostmask", NULL
);
5264 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), NULL
);
5270 nickserv_db_cleanup(UNUSED_ARG(void* extra
))
5272 unreg_del_user_func(nickserv_remove_user
, NULL
);
5273 userList_clean(&curr_helpers
);
5274 policer_params_delete(nickserv_conf
.auth_policer_params
);
5275 dict_delete(nickserv_handle_dict
);
5276 dict_delete(nickserv_nick_dict
);
5277 dict_delete(nickserv_opt_dict
);
5278 dict_delete(nickserv_allow_auth_dict
);
5279 dict_delete(nickserv_email_dict
);
5280 dict_delete(nickserv_id_dict
);
5281 dict_delete(nickserv_conf
.weak_password_dict
);
5282 free(auth_func_list
);
5283 free(auth_func_list_extra
);
5284 free(unreg_func_list
);
5285 free(unreg_func_list_extra
);
5287 free(rf_list_extra
);
5288 free(allowauth_func_list
);
5289 free(allowauth_func_list_extra
);
5290 free(handle_merge_func_list
);
5291 free(handle_merge_func_list_extra
);
5292 free(failpw_func_list
);
5293 free(failpw_func_list_extra
);
5294 if (nickserv_conf
.valid_handle_regex_set
)
5295 regfree(&nickserv_conf
.valid_handle_regex
);
5296 if (nickserv_conf
.valid_nick_regex_set
)
5297 regfree(&nickserv_conf
.valid_nick_regex
);
5300 void handle_loc_auth_oper(struct userNode
*user
, UNUSED_ARG(struct handle_info
*old_handle
), UNUSED_ARG(void *extra
)) {
5301 char *privv
[MAXNUMPARAMS
];
5304 if (!*nickserv_conf
.auto_oper
|| !user
->handle_info
)
5307 if (!IsOper(user
)) {
5308 if (*nickserv_conf
.auto_admin
&& user
->handle_info
->opserv_level
>= opserv_conf_admin_level()) {
5309 if (nickserv_conf
.auto_admin_privs
[0]) {
5310 irc_raw_privs(user
, nickserv_conf
.auto_admin_privs
);
5311 privc
= split_line(strdup(nickserv_conf
.auto_admin_privs
), false, MAXNUMPARAMS
, privv
);
5312 for (i
= 0; i
< privc
; i
++) {
5313 client_modify_priv_by_name(user
, privv
[i
], 1);
5316 irc_umode(user
, nickserv_conf
.auto_admin
);
5317 irc_sno(0x1, "%s (%s@%s) is now an IRC Administrator",
5318 user
->nick
, user
->ident
, user
->hostname
);
5319 send_message(user
, nickserv
, "NSMSG_AUTO_OPER_ADMIN");
5320 } else if (*nickserv_conf
.auto_oper
&& user
->handle_info
->opserv_level
) {
5321 if (nickserv_conf
.auto_oper_privs
[0]) {
5322 irc_raw_privs(user
, nickserv_conf
.auto_oper_privs
);
5323 privc
= split_line(strdup(nickserv_conf
.auto_oper_privs
), false, MAXNUMPARAMS
, privv
);
5324 for (i
= 0; i
< privc
; i
++) {
5325 client_modify_priv_by_name(user
, privv
[i
], 1);
5328 irc_umode(user
, nickserv_conf
.auto_oper
);
5329 irc_sno(0x1, "%s (%s@%s) is now an IRC Operator",
5330 user
->nick
, user
->ident
, user
->hostname
);
5331 send_message(user
, nickserv
, "NSMSG_AUTO_OPER");
5337 init_nickserv(const char *nick
)
5339 struct chanNode
*chan
;
5341 NS_LOG
= log_register_type("NickServ", "file:nickserv.log");
5342 reg_new_user_func(check_user_nick
, NULL
);
5343 reg_nick_change_func(handle_nick_change
, NULL
);
5344 reg_del_user_func(nickserv_remove_user
, NULL
);
5345 reg_account_func(handle_account
);
5346 reg_auth_func(handle_loc_auth_oper
, NULL
);
5348 /* set up handle_inverse_flags */
5349 memset(handle_inverse_flags
, 0, sizeof(handle_inverse_flags
));
5350 for (i
=0; handle_flags
[i
]; i
++) {
5351 handle_inverse_flags
[(unsigned char)handle_flags
[i
]] = i
+ 1;
5352 flag_access_levels
[i
] = 0;
5355 conf_register_reload(nickserv_conf_read
);
5356 nickserv_opt_dict
= dict_new();
5357 nickserv_email_dict
= dict_new();
5359 dict_set_free_keys(nickserv_email_dict
, free
);
5360 dict_set_free_data(nickserv_email_dict
, nickserv_free_email_addr
);
5362 nickserv_module
= module_register("NickServ", NS_LOG
, "nickserv.help", NULL
);
5363 /* Removed qualified_host as default requirement for AUTH, REGISTER, PASS, etc. nets
5364 * can enable it per command using modcmd. (its a shitty default IMO, and now in 1.3
5365 * a big pain to disable since its nolonger in the config file. ) -Rubin
5367 modcmd_register(nickserv_module
, "AUTH", cmd_auth
, 2, MODCMD_KEEP_BOUND
, "flags", "+loghostmask", NULL
);
5368 nickserv_define_func("ALLOWAUTH", cmd_allowauth
, 0, 1, 0);
5369 nickserv_define_func("REGISTER", cmd_register
, -1, 0, 0);
5370 nickserv_define_func("OREGISTER", cmd_oregister
, 0, 1, 0);
5371 nickserv_define_func("UNREGISTER", cmd_unregister
, -1, 1, 0);
5372 nickserv_define_func("OUNREGISTER", cmd_ounregister
, 0, 1, 0);
5373 nickserv_define_func("ADDMASK", cmd_addmask
, -1, 1, 0);
5374 nickserv_define_func("OADDMASK", cmd_oaddmask
, 0, 1, 0);
5375 nickserv_define_func("DELMASK", cmd_delmask
, -1, 1, 0);
5376 nickserv_define_func("ODELMASK", cmd_odelmask
, 0, 1, 0);
5377 nickserv_define_func("ADDSSLFP", cmd_addsslfp
, -1, 1, 0);
5378 nickserv_define_func("OADDSSLFP", cmd_oaddsslfp
, 0, 1, 0);
5379 nickserv_define_func("DELSSLFP", cmd_delsslfp
, -1, 1, 0);
5380 nickserv_define_func("ODELSSLFP", cmd_odelsslfp
, 0, 1, 0);
5381 nickserv_define_func("PASS", cmd_pass
, -1, 1, 0);
5382 nickserv_define_func("SET", cmd_set
, -1, 1, 0);
5383 nickserv_define_func("OSET", cmd_oset
, 0, 1, 0);
5384 nickserv_define_func("ACCOUNTINFO", cmd_handleinfo
, -1, 0, 0);
5385 nickserv_define_func("USERINFO", cmd_userinfo
, -1, 1, 0);
5386 nickserv_define_func("RENAME", cmd_rename_handle
, -1, 1, 0);
5387 nickserv_define_func("VACATION", cmd_vacation
, -1, 1, 0);
5388 nickserv_define_func("MERGE", cmd_merge
, 750, 1, 0);
5389 if (!nickserv_conf
.disable_nicks
) {
5390 /* nick management commands */
5391 nickserv_define_func("REGNICK", cmd_regnick
, -1, 1, 0);
5392 nickserv_define_func("OREGNICK", cmd_oregnick
, 0, 1, 0);
5393 nickserv_define_func("UNREGNICK", cmd_unregnick
, -1, 1, 0);
5394 nickserv_define_func("OUNREGNICK", cmd_ounregnick
, 0, 1, 0);
5395 nickserv_define_func("NICKINFO", cmd_nickinfo
, -1, 1, 0);
5396 nickserv_define_func("RECLAIM", cmd_reclaim
, -1, 1, 0);
5398 if (nickserv_conf
.email_enabled
) {
5399 nickserv_define_func("AUTHCOOKIE", cmd_authcookie
, -1, 0, 0);
5400 nickserv_define_func("RESETPASS", cmd_resetpass
, -1, 0, 0);
5401 nickserv_define_func("COOKIE", cmd_cookie
, -1, 0, 0);
5402 nickserv_define_func("DELCOOKIE", cmd_delcookie
, -1, 1, 0);
5403 nickserv_define_func("ODELCOOKIE", cmd_odelcookie
, 0, 1, 0);
5404 dict_insert(nickserv_opt_dict
, "EMAIL", opt_email
);
5406 nickserv_define_func("GHOST", cmd_ghost
, -1, 1, 0);
5407 /* ignore commands */
5408 nickserv_define_func("ADDIGNORE", cmd_addignore
, -1, 1, 0);
5409 nickserv_define_func("OADDIGNORE", cmd_oaddignore
, 0, 1, 0);
5410 nickserv_define_func("DELIGNORE", cmd_delignore
, -1, 1, 0);
5411 nickserv_define_func("ODELIGNORE", cmd_odelignore
, 0, 1, 0);
5412 /* miscellaneous commands */
5413 nickserv_define_func("STATUS", cmd_status
, -1, 0, 0);
5414 nickserv_define_func("SEARCH", cmd_search
, 100, 1, 0);
5415 nickserv_define_func("SEARCH UNREGISTER", NULL
, 800, 1, 0);
5416 nickserv_define_func("MERGEDB", cmd_mergedb
, 999, 1, 0);
5417 nickserv_define_func("CHECKPASS", cmd_checkpass
, 601, 1, 0);
5418 nickserv_define_func("CHECKEMAIL", cmd_checkemail
, 0, 1, 0);
5420 dict_insert(nickserv_opt_dict
, "INFO", opt_info
);
5421 dict_insert(nickserv_opt_dict
, "WIDTH", opt_width
);
5422 dict_insert(nickserv_opt_dict
, "TABLEWIDTH", opt_tablewidth
);
5423 dict_insert(nickserv_opt_dict
, "COLOR", opt_color
);
5424 dict_insert(nickserv_opt_dict
, "PRIVMSG", opt_privmsg
);
5425 dict_insert(nickserv_opt_dict
, "AUTOHIDE", opt_autohide
);
5426 dict_insert(nickserv_opt_dict
, "STYLE", opt_style
);
5427 dict_insert(nickserv_opt_dict
, "PASS", opt_password
);
5428 dict_insert(nickserv_opt_dict
, "PASSWORD", opt_password
);
5429 dict_insert(nickserv_opt_dict
, "FLAGS", opt_flags
);
5430 dict_insert(nickserv_opt_dict
, "ACCESS", opt_level
);
5431 dict_insert(nickserv_opt_dict
, "LEVEL", opt_level
);
5432 dict_insert(nickserv_opt_dict
, "EPITHET", opt_epithet
);
5433 dict_insert(nickserv_opt_dict
, "NOTE", opt_note
);
5434 if (nickserv_conf
.titlehost_suffix
) {
5435 dict_insert(nickserv_opt_dict
, "TITLE", opt_title
);
5436 dict_insert(nickserv_opt_dict
, "FAKEHOST", opt_fakehost
);
5438 dict_insert(nickserv_opt_dict
, "ANNOUNCEMENTS", opt_announcements
);
5439 dict_insert(nickserv_opt_dict
, "MAXLOGINS", opt_maxlogins
);
5440 dict_insert(nickserv_opt_dict
, "ADVANCED", opt_advanced
);
5441 dict_insert(nickserv_opt_dict
, "LANGUAGE", opt_language
);
5442 dict_insert(nickserv_opt_dict
, "KARMA", opt_karma
);
5444 nickserv_handle_dict
= dict_new();
5445 dict_set_free_keys(nickserv_handle_dict
, free
);
5446 dict_set_free_data(nickserv_handle_dict
, free_handle_info
);
5448 nickserv_id_dict
= dict_new();
5449 dict_set_free_keys(nickserv_id_dict
, free
);
5451 nickserv_nick_dict
= dict_new();
5452 dict_set_free_data(nickserv_nick_dict
, free
);
5454 nickserv_allow_auth_dict
= dict_new();
5456 userList_init(&curr_helpers
);
5459 const char *modes
= conf_get_data("services/nickserv/modes", RECDB_QSTRING
);
5460 nickserv
= AddLocalUser(nick
, nick
, NULL
, "Nick Services", modes
);
5461 nickserv_service
= service_register(nickserv
);
5463 saxdb_register("NickServ", nickserv_saxdb_read
, nickserv_saxdb_write
);
5464 reg_exit_func(nickserv_db_cleanup
, NULL
);
5465 if(nickserv_conf
.handle_expire_frequency
)
5466 timeq_add(now
+ nickserv_conf
.handle_expire_frequency
, expire_handles
, NULL
);
5468 if(autojoin_channels
&& nickserv
) {
5469 for (i
= 0; i
< autojoin_channels
->used
; i
++) {
5470 chan
= AddChannel(autojoin_channels
->list
[i
], now
, "+nt", NULL
, NULL
);
5471 AddChannelUser(nickserv
, chan
)->modes
|= MODE_CHANOP
;
5475 ldap_do_init(nickserv_conf
);
5478 message_register_table(msgtab
);