1 /* nickserv.c - Nick/authentication service
2 * Copyright 2000-2004 srvx Development Team
4 * This file is part of x3.
6 * x3 is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with srvx; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 #include "opserv.h" /* for gag_create(), opserv_bad_channel() */
33 #include <tre/regex.h>
39 #define NICKSERV_CONF_NAME "services/nickserv"
41 #define KEY_DISABLE_NICKS "disable_nicks"
42 #define KEY_DEFAULT_HOSTMASK "default_hostmask"
43 #define KEY_NICKS_PER_HANDLE "nicks_per_handle"
44 #define KEY_NICKS_PER_ACCOUNT "nicks_per_account"
45 #define KEY_PASSWORD_MIN_LENGTH "password_min_length"
46 #define KEY_PASSWORD_MIN_DIGITS "password_min_digits"
47 #define KEY_PASSWORD_MIN_UPPER "password_min_upper"
48 #define KEY_PASSWORD_MIN_LOWER "password_min_lower"
49 #define KEY_VALID_HANDLE_REGEX "valid_handle_regex"
50 #define KEY_VALID_ACCOUNT_REGEX "valid_account_regex"
51 #define KEY_VALID_NICK_REGEX "valid_nick_regex"
52 #define KEY_VALID_FAKEHOST_REGEX "valid_fakehost_regex"
53 #define KEY_DB_BACKUP_FREQ "db_backup_freq"
54 #define KEY_MODOPER_LEVEL "modoper_level"
55 #define KEY_SET_EPITHET_LEVEL "set_epithet_level"
56 #define KEY_SET_TITLE_LEVEL "set_title_level"
57 #define KEY_SET_FAKEHOST_LEVEL "set_fakehost_level"
58 #define KEY_DENIED_FAKEHOST_WORDS "denied_fakehost_words"
59 #define KEY_TITLEHOST_SUFFIX "titlehost_suffix"
60 #define KEY_AUTO_OPER "auto_oper"
61 #define KEY_AUTO_ADMIN "auto_admin"
62 #define KEY_AUTO_OPER_PRIVS "auto_oper_privs"
63 #define KEY_AUTO_ADMIN_PRIVS "auto_admin_privs"
64 #define KEY_FLAG_LEVELS "flag_levels"
65 #define KEY_HANDLE_EXPIRE_FREQ "handle_expire_freq"
66 #define KEY_ACCOUNT_EXPIRE_FREQ "account_expire_freq"
67 #define KEY_HANDLE_EXPIRE_DELAY "handle_expire_delay"
68 #define KEY_NICK_EXPIRE_FREQ "nick_expire_freq"
69 #define KEY_NICK_EXPIRE_DELAY "nick_expire_delay"
70 #define KEY_ACCOUNT_EXPIRE_DELAY "account_expire_delay"
71 #define KEY_NOCHAN_HANDLE_EXPIRE_DELAY "nochan_handle_expire_delay"
72 #define KEY_NOCHAN_ACCOUNT_EXPIRE_DELAY "nochan_account_expire_delay"
73 #define KEY_DICT_FILE "dict_file"
74 #define KEY_NICK "nick"
75 #define KEY_LANGUAGE "language"
76 #define KEY_AUTOGAG_ENABLED "autogag_enabled"
77 #define KEY_AUTOGAG_DURATION "autogag_duration"
78 #define KEY_AUTH_POLICER "auth_policer"
79 #define KEY_EMAIL_VISIBLE_LEVEL "email_visible_level"
80 #define KEY_EMAIL_ENABLED "email_enabled"
81 #define KEY_EMAIL_REQUIRED "email_required"
82 #define KEY_SYNC_LOG "sync_log"
83 #define KEY_COOKIE_TIMEOUT "cookie_timeout"
84 #define KEY_ACCOUNTS_PER_EMAIL "accounts_per_email"
85 #define KEY_EMAIL_SEARCH_LEVEL "email_search_level"
86 #define KEY_DEFAULT_STYLE "default_style"
87 #define KEY_OUNREGISTER_INACTIVE "ounregister_inactive"
88 #define KEY_OUNREGISTER_FLAGS "ounregister_flags"
91 #define KEY_PASSWD "passwd"
92 #define KEY_NICKS "nicks"
93 #define KEY_NICKS_EX "nicks_ex"
94 #define KEY_MASKS "masks"
95 #define KEY_SSLFPS "sslfps"
96 #define KEY_IGNORES "ignores"
97 #define KEY_OPSERV_LEVEL "opserv_level"
98 #define KEY_FLAGS "flags"
99 #define KEY_REGISTER_ON "register"
100 #define KEY_LAST_SEEN "lastseen"
101 #define KEY_INFO "info"
102 #define KEY_USERLIST_STYLE "user_style"
103 #define KEY_SCREEN_WIDTH "screen_width"
104 #define KEY_LAST_AUTHED_HOST "last_authed_host"
105 #define KEY_LAST_QUIT_HOST "last_quit_host"
106 #define KEY_EMAIL_ADDR "email_addr"
107 #define KEY_COOKIE "cookie"
108 #define KEY_COOKIE_DATA "data"
109 #define KEY_COOKIE_TYPE "type"
110 #define KEY_COOKIE_EXPIRES "expires"
111 #define KEY_ACTIVATION "activation"
112 #define KEY_PASSWORD_CHANGE "password change"
113 #define KEY_EMAIL_CHANGE "email change"
114 #define KEY_ALLOWAUTH "allowauth"
115 #define KEY_EPITHET "epithet"
116 #define KEY_TABLE_WIDTH "table_width"
117 #define KEY_ANNOUNCEMENTS "announcements"
118 #define KEY_MAXLOGINS "maxlogins"
119 #define KEY_FAKEHOST "fakehost"
120 #define KEY_NOTE_NOTE "note"
121 #define KEY_NOTE_SETTER "setter"
122 #define KEY_NOTE_DATE "date"
123 #define KEY_KARMA "karma"
124 #define KEY_FORCE_HANDLES_LOWERCASE "force_handles_lowercase"
126 #define KEY_LDAP_ENABLE "ldap_enable"
129 #define KEY_LDAP_URI "ldap_uri"
130 #define KEY_LDAP_BASE "ldap_base"
131 #define KEY_LDAP_DN_FMT "ldap_dn_fmt"
132 #define KEY_LDAP_VERSION "ldap_version"
133 #define KEY_LDAP_AUTOCREATE "ldap_autocreate"
134 #define KEY_LDAP_ADMIN_DN "ldap_admin_dn"
135 #define KEY_LDAP_ADMIN_PASS "ldap_admin_pass"
136 #define KEY_LDAP_FIELD_ACCOUNT "ldap_field_account"
137 #define KEY_LDAP_FIELD_PASSWORD "ldap_field_password"
138 #define KEY_LDAP_FIELD_EMAIL "ldap_field_email"
139 #define KEY_LDAP_FIELD_OSLEVEL "ldap_field_oslevel"
140 #define KEY_LDAP_OBJECT_CLASSES "ldap_object_classes"
141 #define KEY_LDAP_OPER_GROUP_DN "ldap_oper_group_dn"
142 #define KEY_LDAP_OPER_GROUP_LEVEL "ldap_oper_group_level"
143 #define KEY_LDAP_FIELD_GROUP_MEMBER "ldap_field_group_member"
144 #define KEY_LDAP_TIMEOUT "ldap_timeout"
147 #define NICKSERV_VALID_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
149 #define NICKSERV_FUNC(NAME) MODCMD_FUNC(NAME)
150 #define OPTION_FUNC(NAME) int NAME(UNUSED_ARG(struct svccmd *cmd), struct userNode *user, struct handle_info *hi, UNUSED_ARG(unsigned int override), int noreply, unsigned int argc, char *argv[])
151 typedef OPTION_FUNC(option_func_t
);
153 DEFINE_LIST(handle_info_list
, struct handle_info
*)
155 #define NICKSERV_MIN_PARMS(N) do { \
157 reply("MSG_MISSING_PARAMS", argv[0]); \
158 svccmd_send_help_brief(user, nickserv, cmd); \
162 struct userNode
*nickserv
;
163 struct userList curr_helpers
;
164 const char *handle_flags
= HANDLE_FLAGS
;
166 extern struct string_list
*autojoin_channels
;
167 static struct module *nickserv_module
;
168 static struct service
*nickserv_service
;
169 static struct log_type
*NS_LOG
;
170 dict_t nickserv_handle_dict
; /* contains struct handle_info* */
171 static dict_t nickserv_id_dict
; /* contains struct handle_info* */
172 static dict_t nickserv_nick_dict
; /* contains struct nick_info* */
173 static dict_t nickserv_opt_dict
; /* contains option_func_t* */
174 static dict_t nickserv_allow_auth_dict
; /* contains struct handle_info* */
175 static dict_t nickserv_email_dict
; /* contains struct handle_info_list*, indexed by email addr */
176 static char handle_inverse_flags
[256];
177 static unsigned int flag_access_levels
[32];
178 static const struct message_entry msgtab
[] = {
179 { "NSMSG_NO_ANGLEBRACKETS", "The < and > in help indicate that that word is a required parameter, but DO NOT actually type them in messages to me." },
180 { "NSMSG_HANDLE_EXISTS", "Account $b%s$b is already registered." },
181 { "NSMSG_HANDLE_TOLONG", "The account name %s is too long. Account names must be %lu characters or less."},
182 { "NSMSG_PASSWORD_SHORT", "Your password must be at least %lu characters long." },
183 { "NSMSG_PASSWORD_ACCOUNT", "Your password may not be the same as your account name." },
184 { "NSMSG_PASSWORD_DICTIONARY", "Your password is too simple. You must choose a password that is not just a word or name." },
185 { "NSMSG_PASSWORD_READABLE", "Your password must have at least %lu digit(s), %lu capital letter(s), and %lu lower-case letter(s)." },
186 { "NSMSG_LDAP_FAIL", "There was a problem in contacting the account server (ldap): %s. Please try again later." },
187 { "NSMSG_LDAP_FAIL_ADD", "There was a problem in adding account %s to ldap: %s." },
188 { "NSMSG_LDAP_FAIL_SEND_EMAIL", "There was a problem in storing your email address in the account server (ldap): %s. Please try again later." },
189 { "NSMSG_LDAP_FAIL_GET_EMAIL", "There was a problem in retrieving your email address from the account server (ldap): %s. Please try again later." },
190 { "NSMSG_PARTIAL_REGISTER", "Account has been registered to you; nick was already registered to someone else." },
191 { "NSMSG_OREGISTER_VICTIM", "%s has registered a new account for you (named %s)." },
192 { "NSMSG_OREGISTER_H_SUCCESS", "Account has been registered." },
193 { "NSMSG_REGISTER_H_SUCCESS", "Account has been registered to you." },
194 { "NSMSG_REGISTER_HN_SUCCESS", "Account and nick have been registered to you." },
195 { "NSMSG_REQUIRE_OPER", "You must be an $bIRC Operator$b to register the first account." },
196 { "NSMSG_ROOT_HANDLE", "Account %s has been granted $broot-level privileges$b." },
197 { "NSMSG_USE_COOKIE_REGISTER", "To activate your account, you must check your email for the \"cookie\" that has been mailed to it. When you have it, use the $bcookie$b command to complete registration." },
198 { "NSMSG_USE_COOKIE_RESETPASS", "A cookie has been mailed to your account's email address. You must check your email and use the $bcookie$b command to confirm the password change." },
199 { "NSMSG_USE_COOKIE_EMAIL_1", "A cookie has been mailed to the new address you requested. To finish setting your email address, please check your email for the cookie and use the $bcookie$b command to verify." },
200 { "NSMSG_USE_COOKIE_EMAIL_2", "A cookie has been generated, and half mailed to each your old and new addresses. To finish changing your email address, please check your email for the cookie and use the $bcookie$b command to verify." },
201 { "NSMSG_USE_COOKIE_AUTH", "A cookie has been generated and sent to your email address. Once you have checked your email and received the cookie, auth using the $bcookie$b command." },
202 { "NSMSG_COOKIE_LIVE", "Account $b%s$b already has a cookie active. Please either finish using that cookie, wait for it to expire, or auth to the account and use the $bdelcookie$b command." },
203 { "NSMSG_EMAIL_UNACTIVATED", "That email address already has an unused cookie outstanding. Please use the cookie or wait for it to expire." },
204 { "NSMSG_NO_COOKIE", "Your account does not have any cookie issued right now." },
205 { "NSMSG_NO_COOKIE_FOREIGN", "The account $b%s$b does not have any cookie issued right now." },
206 { "NSMSG_CANNOT_COOKIE", "You cannot use that kind of cookie when you are logged in." },
207 { "NSMSG_BAD_COOKIE", "That cookie is not the right one. Please make sure you are copying it EXACTLY from the email; it is case-sensitive, so $bABC$b is different from $babc$b." },
208 { "NSMSG_HANDLE_ACTIVATED", "Your account is now activated (with the password you entered when you registered). You are now authenticated to your account." },
209 { "NSMSG_PASSWORD_CHANGED", "You have successfully changed your password to what you requested with the $bresetpass$b command." },
210 { "NSMSG_EMAIL_PROHIBITED", "%s may not be used as an email address: %s" },
211 { "NSMSG_EMAIL_OVERUSED", "That email address already has an account. Use RESETPASS if you forgot your password." },
212 { "NSMSG_EMAIL_SAME", "That is the email address already there; no need to change it." },
213 { "NSMSG_EMAIL_CHANGED", "You have successfully changed your email address." },
214 { "NSMSG_BAD_COOKIE_TYPE", "Your account had bad cookie type %d; sorry. I am confused. Please report this bug." },
215 { "NSMSG_MUST_TIME_OUT", "You must wait for cookies of that type to time out." },
216 { "NSMSG_ATE_COOKIE", "I ate the cookie for your account. You may now have another." },
217 { "NSMSG_ATE_FOREIGN_COOKIE", "I ate the cookie for account $b%s$b. It may now have another." },
218 { "NSMSG_USE_RENAME", "You are already authenticated to account $b%s$b -- contact the support staff to rename your account." },
219 { "NSMSG_ALREADY_REGISTERING", "You have already used $bREGISTER$b once this session; you may not use it again." },
220 { "NSMSG_REGISTER_BAD_NICKMASK", "You must provide a hostmask, or online nick to generate one automatically. (or set a default hostmask in the config such as *@*)." },
221 { "NSMSG_NICK_NOT_REGISTERED", "Nick $b%s$b has not been registered to any account." },
222 { "NSMSG_HANDLE_NOT_FOUND", "Could not find your account -- did you register yet?" },
223 { "NSMSG_ALREADY_AUTHED", "You are already authed to account $b%s$b; you must reconnect to auth to a different account." },
224 { "NSMSG_USE_AUTHCOOKIE", "Your hostmask is not valid for account $b%1$s$b. Please use the $bauthcookie$b command to grant yourself access. (/msg $S authcookie %1$s)" },
225 { "NSMSG_HOSTMASK_INVALID", "Your hostmask is not valid for account $b%s$b." },
226 { "NSMSG_USER_IS_SERVICE", "$b%s$b is a network service; you can only use that command on real users." },
227 { "NSMSG_USER_PREV_AUTH", "$b%s$b is already authenticated." },
228 { "NSMSG_USER_PREV_STAMP", "$b%s$b has authenticated to an account once and cannot authenticate again." },
229 { "NSMSG_BAD_MAX_LOGINS", "MaxLogins must be at most %d." },
230 { "NSMSG_BAD_ADVANCED", "Advanced must be either 1 to enable it or 0 to disable it." },
231 { "NSMSG_LANGUAGE_NOT_FOUND", "Language $b%s$b is not supported; $b%s$b was the closest available match." },
232 { "NSMSG_MAX_LOGINS", "Your account already has its limit of %d user(s) logged in." },
233 { "NSMSG_STAMPED_REGISTER", "You have already authenticated to an account once this session; you may not register a new account." },
234 { "NSMSG_STAMPED_AUTH", "You have already authenticated to an account once this session; you may not authenticate to another." },
235 { "NSMSG_STAMPED_RESETPASS", "You have already authenticated to an account once this session; you may not reset your password to authenticate again." },
236 { "NSMSG_STAMPED_AUTHCOOKIE", "You have already authenticated to an account once this session; you may not use a cookie to authenticate to another account." },
237 { "NSMSG_TITLE_INVALID", "Titles may contain only a-z, A-Z, 0-9, and '-'. Please choose another." },
238 { "NSMSG_TITLE_TRUNCATED", "That title combined with the user's account name would result in a truncated host; please choose a shorter title." },
239 { "NSMSG_FAKEHOST_INVALID", "Fake hosts must be shorter than %d characters and cannot start with a dot." },
240 { "NSMSG_HANDLEINFO_ON", "$bAccount Information for %s$b" },
241 { "NSMSG_HANDLEINFO_END", "----------End of Account Info-----------" },
242 { "NSMSG_HANDLEINFO_ID", "Account ID: %lu" },
243 { "NSMSG_HANDLEINFO_REGGED", "Registered on: %s" },
244 { "NSMSG_HANDLEINFO_LASTSEEN", "Last seen: %s" },
245 { "NSMSG_HANDLEINFO_LASTSEEN_NOW", "Last seen: Right now!" },
246 { "NSMSG_HANDLEINFO_KARMA", "Karma: %d" },
247 { "NSMSG_HANDLEINFO_VACATION", "On vacation." },
248 { "NSMSG_HANDLEINFO_EMAIL_ADDR", "Email address: %s" },
249 { "NSMSG_HANDLEINFO_COOKIE_ACTIVATION", "Cookie: There is currently an activation cookie issued for this account" },
250 { "NSMSG_HANDLEINFO_COOKIE_PASSWORD", "Cookie: There is currently a password change cookie issued for this account" },
251 { "NSMSG_HANDLEINFO_COOKIE_EMAIL", "Cookie: There is currently an email change cookie issued for this account" },
252 { "NSMSG_HANDLEINFO_COOKIE_ALLOWAUTH", "Cookie: There is currently an allowauth cookie issued for this account" },
253 { "NSMSG_HANDLEINFO_COOKIE_UNKNOWN", "Cookie: There is currently an unknown cookie issued for this account" },
254 { "NSMSG_HANDLEINFO_COOKIE_EMAIL_DATA", "Cookie: New email address: %s" },
255 { "NSMSG_HANDLEINFO_INFOLINE", "Infoline: %s" },
256 { "NSMSG_HANDLEINFO_FLAGS", "Flags: %s" },
257 { "NSMSG_HANDLEINFO_EPITHET", "Epithet: %s" },
258 { "NSMSG_HANDLEINFO_NOTE", "Note (by %s on %s): %s " },
259 { "NSMSG_HANDLEINFO_FAKEHOST", "Fake host: %s" },
260 { "NSMSG_INVALID_KARMA", "$b%s$b is not a valid karma modifier." },
261 { "NSMSG_SET_KARMA", "$bKARMA: $b%d$b" },
262 { "NSMSG_HANDLEINFO_LAST_HOST", "Last quit hostmask: %s" },
263 { "NSMSG_HANDLEINFO_LAST_HOST_UNKNOWN", "Last quit hostmask: Unknown" },
264 { "NSMSG_HANDLEINFO_NICKS", "Nickname(s): %s" },
265 { "NSMSG_HANDLEINFO_MASKS", "Hostmask(s): %s" },
266 { "NSMSG_HANDLEINFO_SSLFPS", "SSL Fingerprints(s): %s" },
267 { "NSMSG_HANDLEINFO_IGNORES", "Ignore(s): %s" },
268 { "NSMSG_HANDLEINFO_CHANNELS", "Channel(s): %s" },
269 { "NSMSG_HANDLEINFO_CURRENT", "Current nickname(s): %s" },
270 { "NSMSG_HANDLEINFO_DNR", "Do-not-register (by %s): %s" },
271 { "NSMSG_USERINFO_AUTHED_AS", "$b%s$b is authenticated to account $b%s$b." },
272 { "NSMSG_USERINFO_NOT_AUTHED", "$b%s$b is not authenticated to any account." },
273 { "NSMSG_NICKINFO_ON", "$bNick Information for %s$b" },
274 { "NSMSG_NICKINFO_END", "----------End of Nick Info-----------" },
275 { "NSMSG_NICKINFO_REGGED", "Registered on: %s" },
276 { "NSMSG_NICKINFO_LASTSEEN", "Last seen: %s" },
277 { "NSMSG_NICKINFO_LASTSEEN_NOW", "Last seen: Right now!" },
278 { "NSMSG_NICKINFO_OWNER", "Account: %s." },
279 { "NSMSG_PASSWORD_INVALID", "Incorrect password; please try again." },
280 { "NSMSG_PLEASE_SET_EMAIL", "We now require email addresses for users. Please use the $bset email$b command to set your email address!" },
281 { "NSMSG_WEAK_PASSWORD", "WARNING: You are using a password that is considered weak (easy to guess). It is STRONGLY recommended you change it (now, if not sooner) by typing \"/msg $S@$s PASS oldpass newpass\" (with your current password and a new password)." },
282 { "NSMSG_HANDLE_SUSPENDED", "Your $b$N$b account has been suspended; you may not use it." },
283 { "NSMSG_AUTH_SUCCESS", "I recognize you." },
284 { "NSMSG_ALLOWAUTH_STAFF", "$b%s$b is a helper or oper; please use $bstaff$b after the account name to allowauth." },
285 { "NSMSG_AUTH_ALLOWED", "User $b%s$b may now authenticate to account $b%s$b." },
286 { "NSMSG_AUTH_ALLOWED_MSG", "You may now authenticate to account $b%s$b by typing $b/msg $N@$s auth %s password$b (using your password). If you will be using this computer regularly, please type $b/msg $N addmask$b (AFTER you auth) to permanently add your hostmask." },
287 { "NSMSG_AUTH_ALLOWED_EMAIL", "You may also (after you auth) type $b/msg $N set email user@your.isp$b to set an email address. This will let you use the $bauthcookie$b command to be authenticated in the future." },
288 { "NSMSG_AUTH_NORMAL_ONLY", "User $b%s$b may now only authenticate to accounts with matching hostmasks." },
289 { "NSMSG_AUTH_UNSPECIAL", "User $b%s$b did not have any special auth allowance." },
290 { "NSMSG_MUST_AUTH", "You must be authenticated first." },
291 { "NSMSG_TOO_MANY_NICKS", "You have already registered the maximum permitted number of nicks." },
292 { "NSMSG_NICK_EXISTS", "Nick $b%s$b already registered." },
293 { "NSMSG_REGNICK_SUCCESS", "Nick $b%s$b has been registered to you." },
294 { "NSMSG_OREGNICK_SUCCESS", "Nick $b%s$b has been registered to account $b%s$b." },
295 { "NSMSG_PASS_SUCCESS", "Password changed." },
296 { "NSMSG_MASK_INVALID", "$b%s$b is an invalid hostmask." },
297 { "NSMSG_ADDMASK_ALREADY", "$b%s$b is already a hostmask in your account." },
298 { "NSMSG_ADDMASK_SUCCESS", "Hostmask %s added." },
299 { "NSMSG_ADDIGNORE_ALREADY", "$b%s$b is already an ignored hostmask in your account." },
300 { "NSMSG_ADDIGNORE_SUCCESS", "Hostmask %s added." },
301 { "NSMSG_ADDSSLFP_ALREADY", "$b%s$b is already an SSL fingerprint in your account." },
302 { "NSMSG_ADDSSLFP_SUCCESS", "SSL fingerprint %s added." },
303 { "NSMSG_DELMASK_NOTLAST", "You may not delete your last hostmask." },
304 { "NSMSG_DELMASK_SUCCESS", "Hostmask %s deleted." },
305 { "NSMSG_DELMASK_NOT_FOUND", "Unable to find mask to be deleted." },
306 { "NSMSG_DELSSLFP_SUCCESS", "SSL fingerprint %s deleted." },
307 { "NSMSG_DELSSLFP_NOT_FOUND", "Unable to find SSL fingerprint to be deleted." },
308 { "NSMSG_OPSERV_LEVEL_BAD", "You may not promote another oper above your level." },
309 { "NSMSG_USE_CMD_PASS", "Please use the PASS command to change your password." },
310 { "NSMSG_UNKNOWN_NICK", "I know nothing about nick $b%s$b." },
311 { "NSMSG_NOT_YOUR_NICK", "The nick $b%s$b is not registered to you." },
312 { "NSMSG_NICK_USER_YOU", "I will not let you kill yourself." },
313 { "NSMSG_UNREGNICK_SUCCESS", "Nick $b%s$b has been unregistered." },
314 { "NSMSG_UNREGISTER_SUCCESS", "Account $b%s$b has been unregistered." },
315 { "NSMSG_UNREGISTER_NICKS_SUCCESS", "Account $b%s$b and all its nicks have been unregistered." },
316 { "NSMSG_UNREGISTER_MUST_FORCE", "Account $b%s$b is not inactive or has special flags set; use FORCE to unregister it." },
317 { "NSMSG_UNREGISTER_CANNOT_FORCE", "Account $b%s$b is not inactive or has special flags set; have an IRCOp use FORCE to unregister it." },
318 { "NSMSG_UNREGISTER_NODELETE", "Account $b%s$b is protected from unregistration." },
319 { "NSMSG_HANDLE_STATS", "There are %d nicks registered to your account." },
320 { "NSMSG_HANDLE_NONE", "You are not authenticated against any account." },
321 { "NSMSG_GLOBAL_STATS", "There are %d accounts and %d nicks registered globally." },
322 { "NSMSG_GLOBAL_STATS_NONICK", "There are %d accounts registered." },
323 { "NSMSG_CANNOT_GHOST_SELF", "You may not ghost-kill yourself." },
324 { "NSMSG_CANNOT_GHOST_USER", "$b%s$b is not authed to your account; you may not ghost-kill them." },
325 { "NSMSG_GHOST_KILLED", "$b%s$b has been killed as a ghost." },
326 { "NSMSG_ON_VACATION", "You are now on vacation. Your account will be preserved until you authenticate again." },
327 { "NSMSG_NO_ACCESS", "Access denied." },
328 { "NSMSG_INVALID_FLAG", "$b%c$b is not a valid $N account flag." },
329 { "NSMSG_SET_FLAG", "Applied flags $b%s$b to %s's $N account." },
330 { "NSMSG_FLAG_PRIVILEGED", "You have insufficient access to set flag %c." },
331 { "NSMSG_DB_UNREADABLE", "Unable to read database file %s; check the log for more information." },
332 { "NSMSG_DB_MERGED", "$N merged DB from %s (in "FMT_TIME_T
".%03lu seconds)." },
333 { "NSMSG_HANDLE_CHANGED", "$b%s$b's account name has been changed to $b%s$b." },
334 { "NSMSG_BAD_HANDLE", "Account $b%s$b is not allowed because it is reserved, is too long, or contains invalid characters." },
335 { "NSMSG_BAD_NICK", "Nickname $b%s$b not registered because it is in use by a network service, is too long, or contains invalid characters." },
336 { "NSMSG_BAD_EMAIL_ADDR", "Please use a well-formed email address." },
337 { "NSMSG_FAIL_RENAME", "Account $b%s$b not renamed to $b%s$b because it is in use by a network services, or contains invalid characters." },
338 { "NSMSG_ACCOUNT_SEARCH_RESULTS", "The following accounts were found:" },
339 { "NSMSG_SEARCH_MATCH", "Match: %s" },
340 { "NSMSG_INVALID_ACTION", "%s is an invalid search action." },
341 { "NSMSG_CANNOT_MERGE_SELF", "You cannot merge account $b%s$b with itself." },
342 { "NSMSG_HANDLES_MERGED", "Merged account $b%s$b into $b%s$b." },
343 { "NSMSG_RECLAIM_WARN", "%s is a registered nick - you must auth to account %s or change your nick." },
344 { "NSMSG_RECLAIM_HOWTO", "To auth to account %s you must use /msg %s@%s AUTH %s <password>" },
345 { "NSMSG_RECLAIM_KILL", "Unauthenticated user of nick." },
346 { "NSMSG_RECLAIMED_NONE", "You cannot manually reclaim a nick." },
347 { "NSMSG_RECLAIMED_WARN", "Sent a request for %s to change their nick." },
348 { "NSMSG_RECLAIMED_SVSNICK", "Forcibly changed %s's nick." },
349 { "NSMSG_RECLAIMED_KILL", "Disconnected %s from the network." },
350 { "NSMSG_CLONE_AUTH", "Warning: %s (%s@%s) authed to your account." },
351 { "NSMSG_SETTING_LIST", "$b$N account settings$b" },
352 { "NSMSG_SETTING_LIST_HEADER", "----------------------------------------" },
353 { "NSMSG_SETTING_LIST_END", "-------------End Of Settings------------" },
354 { "NSMSG_INVALID_OPTION", "$b%s$b is an invalid account setting." },
355 { "NSMSG_INVALID_ANNOUNCE", "$b%s$b is an invalid announcements value." },
356 { "NSMSG_SET_INFO", "$bINFO: $b%s" },
357 { "NSMSG_SET_WIDTH", "$bWIDTH: $b%d" },
358 { "NSMSG_SET_TABLEWIDTH", "$bTABLEWIDTH: $b%d" },
359 { "NSMSG_SET_COLOR", "$bCOLOR: $b%s" },
360 { "NSMSG_SET_PRIVMSG", "$bPRIVMSG: $b%s" },
361 { "NSMSG_SET_STYLE", "$bSTYLE: $b%s" },
362 { "NSMSG_SET_ANNOUNCEMENTS", "$bANNOUNCEMENTS: $b%s" },
363 { "NSMSG_SET_AUTOHIDE", "$bAUTOHIDE: $b%s" },
364 { "NSMSG_SET_PASSWORD", "$bPASSWORD: $b%s" },
365 { "NSMSG_SET_FLAGS", "$bFLAGS: $b%s" },
366 { "NSMSG_SET_EMAIL", "$bEMAIL: $b%s" },
367 { "NSMSG_SET_MAXLOGINS", "$bMAXLOGINS: $b%d" },
368 { "NSMSG_SET_ADVANCED", "$bADVANCED: $b%s" },
369 { "NSMSG_SET_LANGUAGE", "$bLANGUAGE: $b%s" },
370 { "NSMSG_SET_LEVEL", "$bLEVEL: $b%d" },
371 { "NSMSG_SET_EPITHET", "$bEPITHET: $b%s" },
372 { "NSMSG_SET_NOTE", "$bNOTE: $b%s"},
373 { "NSMSG_SET_TITLE", "$bTITLE: $b%s" },
374 { "NSMSG_SET_FAKEHOST", "$bFAKEHOST: $b%s" },
376 { "NSMSG_AUTO_OPER", "You have been auto-opered" },
377 { "NSMSG_AUTO_OPER_ADMIN", "You have been auto-admined" },
379 { "NSEMAIL_ACTIVATION_SUBJECT", "Account verification for %s" },
380 { "NSEMAIL_ACTIVATION_BODY",
381 "This email has been sent to verify that this email address belongs to the person who tried to register an account on %1$s. Your cookie is:\n"
383 "To verify your email address and complete the account registration, log on to %1$s and type the following command:\n"
384 "/msg %3$s@%4$s COOKIE %5$s %2$s\n"
385 "This command is only used once to complete your account registration, and never again. Once you have run this command, you will need to authenticate everytime you reconnect to the network. To do this, you will have to type this command every time you reconnect:\n"
386 "/msg %3$s@%4$s AUTH %5$s your-password\n"
387 "(Please remember to fill in 'your-password' with the actual password you gave to us when you registered.)\n"
388 "OR configure Login-On-Connect (see http://www.afternet.org/login-on-connect for instructions) to connect pre-logged in every time.\n"
390 "If you did NOT request this account, you do not need to do anything.\n"
391 "Please contact the %1$s staff if you have questions, and be sure to check our website." },
392 { "NSEMAIL_ACTIVATION_BODY_WEB",
393 "This email has been sent to verify that this email address belongs to the person who tried to register an account on %1$s. Your cookie is:\n"
395 "To verify your email address and complete the account registration, visit the following URL:\n"
396 "http://www.afternet.org/index.php?option=com_registration&task=activate&username=%5$s&cookie=%2$s\n"
398 "If you did NOT request this account, you do not need to do anything.\n"
399 "Please contact the %1$s staff if you have questions, and be sure to check our website." },
400 { "NSEMAIL_PASSWORD_CHANGE_SUBJECT", "Password change verification on %s" },
401 { "NSEMAIL_PASSWORD_CHANGE_BODY",
402 "This email has been sent to verify that you wish to change the password on your account %5$s. Your cookie is %2$s.\n"
403 "To complete the password change, log on to %1$s and type the following command:\n"
404 "/msg %3$s@%4$s COOKIE %5$s %2$s\n"
405 "If you did NOT request your password to be changed, you do not need to do anything.\n"
406 "Please contact the %1$s staff if you have questions." },
407 { "NSEMAIL_PASSWORD_CHANGE_BODY_WEB",
408 "This email has been sent to verify that you wish to change the password on your account %5$s. Your cookie is %2$s.\n"
409 "To complete the password change, click the following URL:\n"
410 "http://www.afternet.org/index.php?option=com_registration&task=passcookie&username=%5$s&cookie=%2$s\n"
411 "If you did NOT request your password to be changed, you do not need to do anything.\n"
412 "Please contact the %1$s staff if you have questions." },
413 { "NSEMAIL_EMAIL_CHANGE_SUBJECT", "Email address change verification for %s" },
414 #ifdef stupid_verify_old_email
415 { "NSEMAIL_EMAIL_CHANGE_BODY_NEW", "This email has been sent to verify that your email address belongs to the same person as account %5$s on %1$s. The SECOND HALF of your cookie is %2$.*6$s.\nTo verify your address as associated with this account, log on to %1$s and type the following command:\n /msg %3$s@%4$s COOKIE %5$s ?????%2$.*6$s\n(Replace the ????? with the FIRST HALF of the cookie, as sent to your OLD email address.)\nIf you did NOT request this email address to be associated with this account, you do not need to do anything. Please contact the %1$s staff if you have questions." },
416 { "NSEMAIL_EMAIL_CHANGE_BODY_OLD", "This email has been sent to verify that you want to change your email for account %5$s on %1$s from this address to %7$s. The FIRST HALF of your cookie is %2$.*6$s\nTo verify your new address as associated with this account, log on to %1$s and type the following command:\n /msg %3$s@%4$s COOKIE %5$s %2$.*6$s?????\n(Replace the ????? with the SECOND HALF of the cookie, as sent to your NEW email address.)\nIf you did NOT request this change of email address, you do not need to do anything. Please contact the %1$s staff if you have questions." },
418 { "NSEMAIL_EMAIL_VERIFY_SUBJECT", "Email address verification for %s" },
419 { "NSEMAIL_EMAIL_VERIFY_BODY", "This email has been sent to verify that this address belongs to the same person as %5$s on %1$s. Your cookie is %2$s.\nTo verify your address as associated with this account, log on to %1$s and type the following command:\n /msg %3$s@%4$s COOKIE %5$s %2$s\nIf you did NOT request this email address to be associated with this account, you do not need to do anything. Please contact the %1$s staff if you have questions." },
420 { "NSEMAIL_ALLOWAUTH_SUBJECT", "Authentication allowed for %s" },
421 { "NSEMAIL_ALLOWAUTH_BODY", "This email has been sent to let you authenticate (auth) to account %5$s on %1$s. Your cookie is %2$s.\nTo auth to that account, log on to %1$s and type the following command:\n /msg %3$s@%4$s COOKIE %5$s %2$s\nIf you did NOT request this authorization, you do not need to do anything. Please contact the %1$s staff if you have questions." },
422 { "NSMSG_NOT_VALID_FAKEHOST_DOT", "$b%s$b is not a valid vhost. (needs at least one dot)" },
423 { "NSMSG_NOT_VALID_FAKEHOST_AT", "$b%s$b is not a valid vhost. (it can not have a '@')" },
424 { "NSMSG_DENIED_FAKEHOST_WORD", "Access denied because there's a prohibited word in $b%s$b (%s)." },
425 { "NSMSG_NOT_VALID_FAKEHOST_LEN", "$b%s$b is not a valid vhost. (can only be 63 characters)" },
426 { "NSMSG_NOT_VALID_FAKEHOST_TLD_LEN", "$b%s$b is not a valid vhost. (TLD can only be 4 characters and less)" },
427 { "NSMSG_NOT_VALID_FAKEHOST_REGEX", "$b%s$b is not allowed by the admin, consult the valid vhost regex pattern in the config file under nickserv/valid_fakehost_regex." },
428 { "CHECKPASS_YES", "Yes." },
429 { "CHECKPASS_NO", "No." },
430 { "CHECKEMAIL_NOT_SET", "No email set." },
431 { "CHECKEMAIL_YES", "Yes." },
432 { "CHECKEMAIL_NO", "No." },
433 { "NSMSG_DEFCON_NO_NEW_NICKS", "You cannot register new %s at this time, please try again soon" },
437 static void nickserv_reclaim(struct userNode
*user
, struct nick_info
*ni
, enum reclaim_action action
);
438 static void nickserv_reclaim_p(void *data
);
439 static int nickserv_addmask(struct userNode
*user
, struct handle_info
*hi
, const char *mask
);
441 struct nickserv_config nickserv_conf
;
443 /* We have 2^32 unique account IDs to use. */
444 unsigned long int highest_id
= 0;
447 canonicalize_hostmask(char *mask
)
449 char *out
= mask
, *temp
;
450 if ((temp
= strchr(mask
, '!'))) {
452 while (*temp
) *out
++ = *temp
++;
458 static struct handle_note
*
459 nickserv_add_note(const char *setter
, time_t date
, const char *text
)
461 struct handle_note
*note
= calloc(1, sizeof(*note
) + strlen(text
));
463 strncpy(note
->setter
, setter
, sizeof(note
->setter
)-1);
465 memcpy(note
->note
, text
, strlen(text
));
469 static struct handle_info
*
470 register_handle(const char *handle
, const char *passwd
, UNUSED_ARG(unsigned long id
))
472 struct handle_info
*hi
;
474 hi
= calloc(1, sizeof(*hi
));
475 hi
->userlist_style
= nickserv_conf
.default_style
? nickserv_conf
.default_style
: HI_DEFAULT_STYLE
;
476 hi
->announcements
= '?';
477 hi
->handle
= strdup(handle
);
478 safestrncpy(hi
->passwd
, passwd
, sizeof(hi
->passwd
));
480 dict_insert(nickserv_handle_dict
, hi
->handle
, hi
);
486 register_nick(const char *nick
, struct handle_info
*owner
)
488 struct nick_info
*ni
;
489 ni
= malloc(sizeof(struct nick_info
));
490 safestrncpy(ni
->nick
, nick
, sizeof(ni
->nick
));
491 ni
->registered
= now
;
494 ni
->next
= owner
->nicks
;
496 dict_insert(nickserv_nick_dict
, ni
->nick
, ni
);
500 delete_nick(struct nick_info
*ni
)
502 struct nick_info
*last
, *next
;
503 struct userNode
*user
;
504 /* Check to see if we should mark a user as unregistered. */
505 if ((user
= GetUserH(ni
->nick
)) && IsReggedNick(user
)) {
506 user
->modes
&= ~FLAGS_REGNICK
;
509 /* Remove ni from the nick_info linked list. */
510 if (ni
== ni
->owner
->nicks
) {
511 ni
->owner
->nicks
= ni
->next
;
513 last
= ni
->owner
->nicks
;
519 last
->next
= next
->next
;
521 dict_remove(nickserv_nick_dict
, ni
->nick
);
524 static unreg_func_t
*unreg_func_list
;
525 static void **unreg_func_list_extra
;
526 static unsigned int unreg_func_size
= 0, unreg_func_used
= 0;
529 reg_unreg_func(unreg_func_t func
, void *extra
)
531 if (unreg_func_used
== unreg_func_size
) {
532 if (unreg_func_size
) {
533 unreg_func_size
<<= 1;
534 unreg_func_list
= realloc(unreg_func_list
, unreg_func_size
*sizeof(unreg_func_t
));
535 unreg_func_list_extra
= realloc(unreg_func_list_extra
, unreg_func_size
*sizeof(void*));
538 unreg_func_list
= malloc(unreg_func_size
*sizeof(unreg_func_t
));
539 unreg_func_list_extra
= malloc(unreg_func_size
*sizeof(void*));
542 unreg_func_list
[unreg_func_used
] = func
;
543 unreg_func_list_extra
[unreg_func_used
++] = extra
;
547 nickserv_free_cookie(void *data
)
549 struct handle_cookie
*cookie
= data
;
550 if (cookie
->hi
) cookie
->hi
->cookie
= NULL
;
551 if (cookie
->data
) free(cookie
->data
);
556 free_handle_info(void *vhi
)
558 struct handle_info
*hi
= vhi
;
560 free_string_list(hi
->masks
);
561 free_string_list(hi
->sslfps
);
562 free_string_list(hi
->ignores
);
566 delete_nick(hi
->nicks
);
572 timeq_del(hi
->cookie
->expires
, nickserv_free_cookie
, hi
->cookie
, 0);
573 nickserv_free_cookie(hi
->cookie
);
575 if (hi
->email_addr
) {
576 struct handle_info_list
*hil
= dict_find(nickserv_email_dict
, hi
->email_addr
, NULL
);
577 handle_info_list_remove(hil
, hi
);
579 dict_remove(nickserv_email_dict
, hi
->email_addr
);
584 static void set_user_handle_info(struct userNode
*user
, struct handle_info
*hi
, int stamp
);
587 nickserv_unregister_handle(struct handle_info
*hi
, struct userNode
*notify
, struct userNode
*bot
)
590 struct userNode
*uNode
;
593 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
595 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
596 if( (rc
= ldap_delete_account(hi
->handle
)) != LDAP_SUCCESS
) {
598 send_message(notify
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
600 if(rc
!= LDAP_NO_SUCH_OBJECT
)
601 return false; /* if theres noone there to delete, its kinda ok, right ?:) */
606 for (n
=0; n
<unreg_func_used
; n
++)
607 unreg_func_list
[n
](notify
, hi
, unreg_func_list_extra
[n
]);
609 if (nickserv_conf
.sync_log
) {
610 uNode
= GetUserH(hi
->users
->nick
);
614 set_user_handle_info(hi
->users
, NULL
, 0);
617 if (nickserv_conf
.disable_nicks
)
618 send_message(notify
, bot
, "NSMSG_UNREGISTER_SUCCESS", hi
->handle
);
620 send_message(notify
, bot
, "NSMSG_UNREGISTER_NICKS_SUCCESS", hi
->handle
);
623 if (nickserv_conf
.sync_log
)
624 SyncLog("UNREGISTER %s", hi
->handle
);
626 dict_remove(nickserv_handle_dict
, hi
->handle
);
631 get_handle_info(const char *handle
)
633 return dict_find(nickserv_handle_dict
, handle
, 0);
637 get_nick_info(const char *nick
)
639 return nickserv_conf
.disable_nicks
? 0 : dict_find(nickserv_nick_dict
, nick
, 0);
643 find_handle_in_channel(struct chanNode
*channel
, struct handle_info
*handle
, struct userNode
*except
)
648 for (nn
=0; nn
<channel
->members
.used
; ++nn
) {
649 mn
= channel
->members
.list
[nn
];
650 if ((mn
->user
!= except
) && (mn
->user
->handle_info
== handle
))
657 oper_has_access(struct userNode
*user
, struct userNode
*bot
, unsigned int min_level
, unsigned int quiet
) {
658 if (!user
->handle_info
) {
660 send_message(user
, bot
, "MSG_AUTHENTICATE");
664 if (!IsOper(user
) && (!IsHelping(user
) || min_level
)) {
666 send_message(user
, bot
, "NSMSG_NO_ACCESS");
670 if (HANDLE_FLAGGED(user
->handle_info
, OPER_SUSPENDED
)) {
672 send_message(user
, bot
, "MSG_OPER_SUSPENDED");
676 if (user
->handle_info
->opserv_level
< min_level
) {
678 send_message(user
, bot
, "NSMSG_NO_ACCESS");
686 is_valid_handle(const char *handle
)
688 struct userNode
*user
;
689 /* cant register a juped nick/service nick as handle, to prevent confusion */
690 user
= GetUserH(handle
);
691 if (user
&& IsLocal(user
))
693 /* check against maximum length */
694 if (strlen(handle
) > NICKSERV_HANDLE_LEN
)
696 /* for consistency, only allow account names that could be nicks */
697 if (!is_valid_nick(handle
))
699 /* disallow account names that look like bad words */
700 if (opserv_bad_channel(handle
))
702 /* test either regex or containing all valid chars */
703 if (nickserv_conf
.valid_handle_regex_set
) {
704 int err
= regexec(&nickserv_conf
.valid_handle_regex
, handle
, 0, 0, 0);
707 buff
[regerror(err
, &nickserv_conf
.valid_handle_regex
, buff
, sizeof(buff
))] = 0;
708 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
712 return !handle
[strspn(handle
, NICKSERV_VALID_CHARS
)];
717 is_registerable_nick(const char *nick
)
719 struct userNode
*user
;
720 /* cant register a juped nick/service nick as nick, to prevent confusion */
721 user
= GetUserH(nick
);
722 if (user
&& IsLocal(user
))
724 /* for consistency, only allow nicks names that could be nicks */
725 if (!is_valid_nick(nick
))
727 /* disallow nicks that look like bad words */
728 if (opserv_bad_channel(nick
))
731 if (strlen(nick
) > NICKLEN
)
733 /* test either regex or as valid handle */
734 if (nickserv_conf
.valid_nick_regex_set
) {
735 int err
= regexec(&nickserv_conf
.valid_nick_regex
, nick
, 0, 0, 0);
738 buff
[regerror(err
, &nickserv_conf
.valid_nick_regex
, buff
, sizeof(buff
))] = 0;
739 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
745 /* this has been replaced with one in tools.c
748 is_valid_email_addr(const char *email)
750 return strchr(email, '@') != NULL;
756 visible_email_addr(struct userNode
*user
, struct handle_info
*hi
)
758 if (hi
->email_addr
) {
759 if (oper_has_access(user
, nickserv
, nickserv_conf
.email_visible_level
, 1)) {
760 return hi
->email_addr
;
770 smart_get_handle_info(struct userNode
*service
, struct userNode
*user
, const char *name
)
772 struct handle_info
*hi
;
773 struct userNode
*target
;
777 if (!(hi
= get_handle_info(++name
))) {
778 send_message(user
, service
, "MSG_HANDLE_UNKNOWN", name
);
783 if (!(target
= GetUserH(name
))) {
784 send_message(user
, service
, "MSG_NICK_UNKNOWN", name
);
787 if (IsLocal(target
)) {
788 if (IsService(target
))
789 send_message(user
, service
, "NSMSG_USER_IS_SERVICE", target
->nick
);
791 send_message(user
, service
, "MSG_USER_AUTHENTICATE", target
->nick
);
794 if (!(hi
= target
->handle_info
)) {
795 send_message(user
, service
, "MSG_USER_AUTHENTICATE", target
->nick
);
803 oper_outranks(struct userNode
*user
, struct handle_info
*hi
) {
804 if (user
->handle_info
->opserv_level
> hi
->opserv_level
)
806 if (user
->handle_info
->opserv_level
== hi
->opserv_level
) {
807 if ((user
->handle_info
->opserv_level
== 1000)
808 || (user
->handle_info
== hi
)
809 || ((user
->handle_info
->opserv_level
== 0)
810 && !(HANDLE_FLAGGED(hi
, SUPPORT_HELPER
) || HANDLE_FLAGGED(hi
, NETWORK_HELPER
))
811 && HANDLE_FLAGGED(user
->handle_info
, HELPING
))) {
815 send_message(user
, nickserv
, "MSG_USER_OUTRANKED", hi
->handle
);
820 get_victim_oper(struct userNode
*user
, const char *target
)
822 struct handle_info
*hi
;
823 if (!(hi
= smart_get_handle_info(nickserv
, user
, target
)))
825 if (HANDLE_FLAGGED(user
->handle_info
, OPER_SUSPENDED
)) {
826 send_message(user
, nickserv
, "MSG_OPER_SUSPENDED");
829 return oper_outranks(user
, hi
) ? hi
: NULL
;
833 valid_user_for(struct userNode
*user
, struct handle_info
*hi
)
837 /* If no hostmasks on the account, allow it. */
838 if (!hi
->masks
->used
)
840 /* If any hostmask matches, allow it. */
841 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
842 if (user_matches_glob(user
, hi
->masks
->list
[ii
], 0, 0))
844 /* If they are allowauthed to this account, allow it (removing the aa). */
845 if (dict_find(nickserv_allow_auth_dict
, user
->nick
, NULL
) == hi
) {
846 dict_remove(nickserv_allow_auth_dict
, user
->nick
);
849 /* The user is not allowed to use this account. */
854 valid_user_sslfp(struct userNode
*user
, struct handle_info
*hi
)
858 if (!hi
->sslfps
->used
)
863 /* If any SSL fingerprint matches, allow it. */
864 for (ii
=0; ii
<hi
->sslfps
->used
; ii
++)
865 if (!irccasecmp(user
->sslfp
, hi
->sslfps
->list
[ii
]))
868 /* No valid SSL fingerprint found. */
873 is_secure_password(const char *handle
, const char *pass
, struct userNode
*user
)
876 unsigned int cnt_digits
= 0, cnt_upper
= 0, cnt_lower
= 0;
880 if (len
< nickserv_conf
.password_min_length
) {
882 send_message(user
, nickserv
, "NSMSG_PASSWORD_SHORT", nickserv_conf
.password_min_length
);
885 if (!irccasecmp(pass
, handle
)) {
887 send_message(user
, nickserv
, "NSMSG_PASSWORD_ACCOUNT");
890 dict_find(nickserv_conf
.weak_password_dict
, pass
, &p
);
893 send_message(user
, nickserv
, "NSMSG_PASSWORD_DICTIONARY");
896 for (i
=0; i
<len
; i
++) {
897 if (isdigit(pass
[i
]))
899 if (isupper(pass
[i
]))
901 if (islower(pass
[i
]))
904 if ((cnt_lower
< nickserv_conf
.password_min_lower
)
905 || (cnt_upper
< nickserv_conf
.password_min_upper
)
906 || (cnt_digits
< nickserv_conf
.password_min_digits
)) {
908 send_message(user
, nickserv
, "NSMSG_PASSWORD_READABLE", nickserv_conf
.password_min_digits
, nickserv_conf
.password_min_upper
, nickserv_conf
.password_min_lower
);
914 static auth_func_t
*auth_func_list
;
915 static void **auth_func_list_extra
;
916 static unsigned int auth_func_size
= 0, auth_func_used
= 0;
919 reg_auth_func(auth_func_t func
, void *extra
)
921 if (auth_func_used
== auth_func_size
) {
922 if (auth_func_size
) {
923 auth_func_size
<<= 1;
924 auth_func_list
= realloc(auth_func_list
, auth_func_size
*sizeof(auth_func_t
));
925 auth_func_list_extra
= realloc(auth_func_list_extra
, auth_func_size
*sizeof(void*));
928 auth_func_list
= malloc(auth_func_size
*sizeof(auth_func_t
));
929 auth_func_list_extra
= malloc(auth_func_size
*sizeof(void*));
932 auth_func_list
[auth_func_used
] = func
;
933 auth_func_list_extra
[auth_func_used
++] = extra
;
936 static handle_rename_func_t
*rf_list
;
937 static void **rf_list_extra
;
938 static unsigned int rf_list_size
, rf_list_used
;
941 reg_handle_rename_func(handle_rename_func_t func
, void *extra
)
943 if (rf_list_used
== rf_list_size
) {
946 rf_list
= realloc(rf_list
, rf_list_size
*sizeof(rf_list
[0]));
947 rf_list_extra
= realloc(rf_list_extra
, rf_list_size
*sizeof(void*));
950 rf_list
= malloc(rf_list_size
*sizeof(rf_list
[0]));
951 rf_list_extra
= malloc(rf_list_size
*sizeof(void*));
954 rf_list
[rf_list_used
] = func
;
955 rf_list_extra
[rf_list_used
++] = extra
;
959 generate_fakehost(struct handle_info
*handle
)
961 struct userNode
*target
;
962 extern const char *hidden_host_suffix
;
963 static char buffer
[HOSTLEN
+1];
967 if (!handle
->fakehost
) {
968 data
= conf_get_data("server/hidden_host_type", RECDB_QSTRING
);
973 snprintf(buffer
, sizeof(buffer
), "%s.%s", handle
->handle
, hidden_host_suffix
);
974 else if (style
== 2) {
975 /* Due to the way fakehost is coded theres no way i can
976 get the exact user, so for now ill just take the first
978 for (target
= handle
->users
; target
; target
= target
->next_authed
)
982 snprintf(buffer
, sizeof(buffer
), "%s", target
->crypthost
);
984 strncpy(buffer
, "none", sizeof(buffer
));
987 } else if (handle
->fakehost
[0] == '.') {
988 /* A leading dot indicates the stored value is actually a title. */
989 snprintf(buffer
, sizeof(buffer
), "%s.%s.%s", handle
->handle
, handle
->fakehost
+1, nickserv_conf
.titlehost_suffix
);
992 return handle
->fakehost
;
996 apply_fakehost(struct handle_info
*handle
)
998 struct userNode
*target
;
1003 fake
= generate_fakehost(handle
);
1004 for (target
= handle
->users
; target
; target
= target
->next_authed
)
1005 assign_fakehost(target
, fake
, 1);
1008 void send_func_list(struct userNode
*user
)
1011 struct handle_info
*old_info
;
1013 old_info
= user
->handle_info
;
1015 for (n
=0; n
<auth_func_used
; n
++)
1016 auth_func_list
[n
](user
, old_info
, auth_func_list_extra
[n
]);
1020 set_user_handle_info(struct userNode
*user
, struct handle_info
*hi
, int stamp
)
1023 struct handle_info
*old_info
;
1025 /* This can happen if somebody uses COOKIE while authed, or if
1026 * they re-auth to their current handle (which is silly, but users
1027 * are like that). */
1028 if (user
->handle_info
== hi
)
1031 if (user
->handle_info
) {
1032 struct userNode
*other
;
1033 struct nick_info
* ni
;
1036 userList_remove(&curr_helpers
, user
);
1038 /* remove from next_authed linked list */
1039 if (user
->handle_info
->users
== user
) {
1040 user
->handle_info
->users
= user
->next_authed
;
1041 } else if (user
->handle_info
->users
!= NULL
) {
1042 for (other
= user
->handle_info
->users
;
1043 other
->next_authed
!= user
;
1044 other
= other
->next_authed
) ;
1045 other
->next_authed
= user
->next_authed
;
1047 /* No users authed to the account - can happen if they get
1048 * killed for authing. */
1050 /* if nobody left on old handle, and they're not an oper, remove !god */
1051 if (!user
->handle_info
->users
&& !user
->handle_info
->opserv_level
)
1052 HANDLE_CLEAR_FLAG(user
->handle_info
, HELPING
);
1053 /* record them as being last seen at this time */
1054 user
->handle_info
->lastseen
= now
;
1055 if ((ni
= get_nick_info(user
->nick
)))
1057 /* and record their hostmask */
1058 snprintf(user
->handle_info
->last_quit_host
, sizeof(user
->handle_info
->last_quit_host
), "%s@%s", user
->ident
, user
->hostname
);
1060 old_info
= user
->handle_info
;
1061 user
->handle_info
= hi
;
1062 if (hi
&& !hi
->users
&& !hi
->opserv_level
)
1063 HANDLE_CLEAR_FLAG(hi
, HELPING
);
1065 /* Call auth handlers */
1066 if (!GetUserH(user
->nick
))
1070 struct nick_info
*ni
;
1072 HANDLE_CLEAR_FLAG(hi
, FROZEN
);
1073 if (nickserv_conf
.warn_clone_auth
) {
1074 struct userNode
*other
;
1075 for (other
= hi
->users
; other
; other
= other
->next_authed
)
1076 send_message(other
, nickserv
, "NSMSG_CLONE_AUTH", user
->nick
, user
->ident
, user
->hostname
);
1079 /* Add this auth to users list of current auths */
1080 user
->next_authed
= hi
->users
;
1083 /* Add to helpers list */
1084 if (IsHelper(user
) && !userList_contains(&curr_helpers
, user
))
1085 userList_append(&curr_helpers
, user
);
1087 /* Set the fakehost */
1088 if (hi
->fakehost
|| old_info
)
1092 #ifdef WITH_PROTOCOL_P10
1093 /* Stamp users with their account name. */
1094 char *id
= hi
->handle
;
1096 const char *id
= "???";
1098 /* Mark all the nicks registered to this
1099 * account as registered nicks
1100 * - Why not just this one? -rubin */
1101 if (!nickserv_conf
.disable_nicks
) {
1102 struct nick_info
*ni2
;
1103 for (ni2
= hi
->nicks
; ni2
; ni2
= ni2
->next
) {
1104 if (!irccasecmp(user
->nick
, ni2
->nick
)) {
1105 user
->modes
|= FLAGS_REGNICK
;
1110 /* send the account to the ircd */
1111 StampUser(user
, id
, hi
->registered
);
1114 /* Stop trying to kick this user off their nick */
1115 if ((ni
= get_nick_info(user
->nick
)) && (ni
->owner
== hi
)) {
1116 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
1120 /* We cannot clear the user's account ID, unfortunately. */
1121 user
->next_authed
= NULL
;
1124 /* Call auth handlers */
1125 if (GetUserH(user
->nick
)) {
1126 for (n
=0; n
<auth_func_used
; n
++) {
1127 auth_func_list
[n
](user
, old_info
, auth_func_list_extra
[n
]);
1134 static struct handle_info
*
1135 nickserv_register(struct userNode
*user
, struct userNode
*settee
, const char *handle
, const char *passwd
, int no_auth
)
1137 struct handle_info
*hi
;
1138 struct nick_info
*ni
;
1139 char crypted
[MD5_CRYPT_LENGTH
] = "";
1141 if ((hi
= dict_find(nickserv_handle_dict
, handle
, NULL
))) {
1143 send_message(user
, nickserv
, "NSMSG_HANDLE_EXISTS", handle
);
1147 if(strlen(handle
) > 30)
1150 send_message(user
, nickserv
, "NSMSG_HANDLE_TOLONG", handle
, 30);
1156 if (!is_secure_password(handle
, passwd
, user
))
1159 cryptpass(passwd
, crypted
);
1162 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1164 rc
= ldap_do_add(handle
, (no_auth
|| !passwd
? NULL
: crypted
), NULL
);
1165 if(LDAP_SUCCESS
!= rc
&& LDAP_ALREADY_EXISTS
!= rc
) {
1167 send_message(user
, nickserv
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
1172 hi
= register_handle(handle
, crypted
, 0);
1173 hi
->masks
= alloc_string_list(1);
1174 hi
->sslfps
= alloc_string_list(1);
1175 hi
->ignores
= alloc_string_list(1);
1177 hi
->language
= lang_C
;
1178 hi
->registered
= now
;
1180 hi
->flags
= HI_DEFAULT_FLAGS
;
1181 if (settee
&& !no_auth
)
1182 set_user_handle_info(settee
, hi
, 1);
1184 if (user
!= settee
) {
1186 send_message(user
, nickserv
, "NSMSG_OREGISTER_H_SUCCESS");
1188 else if (nickserv_conf
.disable_nicks
) {
1190 send_message(user
, nickserv
, "NSMSG_REGISTER_H_SUCCESS");
1193 else if (user
&& (ni
= dict_find(nickserv_nick_dict
, user
->nick
, NULL
))) {
1195 send_message(user
, nickserv
, "NSMSG_PARTIAL_REGISTER");
1200 if (is_registerable_nick(user
->nick
)) {
1201 register_nick(user
->nick
, hi
);
1202 send_message(user
, nickserv
, "NSMSG_REGISTER_HN_SUCCESS");
1206 if (is_registerable_nick(handle
)) {
1207 register_nick(handle
, hi
);
1211 if (settee
&& (user
!= settee
)) {
1213 send_message(settee
, nickserv
, "NSMSG_OREGISTER_VICTIM", user
->nick
, hi
->handle
);
1220 nickserv_bake_cookie(struct handle_cookie
*cookie
)
1222 cookie
->hi
->cookie
= cookie
;
1223 timeq_add(cookie
->expires
, nickserv_free_cookie
, cookie
);
1226 /* Contributed by the great sneep of afternet ;) */
1227 /* Since this gets used in a URL, we want to avoid stuff that confuses
1228 * email clients such as ] and ?. a-z, 0-9 only.
1230 void genpass(char *str
, int len
)
1235 for(i
= 0; i
< len
; i
++)
1239 c
= (char)((float)rand() / (float)RAND_MAX
* (float)256);
1240 } while(!((c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z') || (c
>= '0' && c
<= '9')));
1248 nickserv_make_cookie(struct userNode
*user
, struct handle_info
*hi
, enum cookie_type type
, const char *cookie_data
, int weblink
)
1250 struct handle_cookie
*cookie
;
1251 char subject
[128], body
[4096], *misc
;
1252 const char *netname
, *fmt
;
1256 send_message(user
, nickserv
, "NSMSG_COOKIE_LIVE", hi
->handle
);
1260 cookie
= calloc(1, sizeof(*cookie
));
1262 cookie
->type
= type
;
1263 cookie
->data
= cookie_data
? strdup(cookie_data
) : NULL
;
1265 cookie
->expires
= now
+ nickserv_conf
.cookie_timeout
;
1266 /* Adding dedicated password gen function for more control -Rubin */
1267 genpass(cookie
->cookie
, 10);
1269 *inttobase64(cookie->cookie, rand(), 5);
1270 *inttobase64(cookie->cookie+5, rand(), 5);
1273 netname
= nickserv_conf
.network_name
;
1276 switch (cookie
->type
) {
1278 hi
->passwd
[0] = 0; /* invalidate password */
1279 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_REGISTER");
1280 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_SUBJECT");
1281 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1284 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_BODY_WEB");
1286 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_BODY");
1288 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1291 case PASSWORD_CHANGE
:
1292 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_RESETPASS");
1293 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_SUBJECT");
1294 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1296 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_BODY_WEB");
1298 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_BODY");
1299 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1303 misc
= hi
->email_addr
;
1304 hi
->email_addr
= cookie
->data
;
1305 #ifdef stupid_verify_old_email
1307 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_EMAIL_2");
1308 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_SUBJECT");
1309 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1310 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_BODY_NEW");
1311 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
+COOKIELEN
/2, nickserv
->nick
, self
->name
, hi
->handle
, COOKIELEN
/2);
1312 mail_send(nickserv
, hi
, subject
, body
, 1);
1313 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_BODY_OLD");
1314 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
, COOKIELEN
/2, hi
->email_addr
);
1318 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_EMAIL_1");
1319 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_VERIFY_SUBJECT");
1320 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1321 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_VERIFY_BODY");
1322 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1323 mail_send(nickserv
, hi
, subject
, body
, 1);
1325 #ifdef stupid_verify_old_email
1328 hi
->email_addr
= misc
;
1331 fmt
= handle_find_message(hi
, "NSEMAIL_ALLOWAUTH_SUBJECT");
1332 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1333 fmt
= handle_find_message(hi
, "NSEMAIL_ALLOWAUTH_BODY");
1334 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1335 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_AUTH");
1338 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d in nickserv_make_cookie.", cookie
->type
);
1342 mail_send(nickserv
, hi
, subject
, body
, first_time
);
1343 nickserv_bake_cookie(cookie
);
1347 nickserv_eat_cookie(struct handle_cookie
*cookie
)
1349 cookie
->hi
->cookie
= NULL
;
1350 timeq_del(cookie
->expires
, nickserv_free_cookie
, cookie
, 0);
1351 nickserv_free_cookie(cookie
);
1355 nickserv_free_email_addr(void *data
)
1357 handle_info_list_clean(data
);
1362 nickserv_set_email_addr(struct handle_info
*hi
, const char *new_email_addr
)
1364 struct handle_info_list
*hil
;
1365 /* Remove from old handle_info_list ... */
1366 if (hi
->email_addr
&& (hil
= dict_find(nickserv_email_dict
, hi
->email_addr
, 0))) {
1367 handle_info_list_remove(hil
, hi
);
1368 if (!hil
->used
) dict_remove(nickserv_email_dict
, hil
->tag
);
1369 hi
->email_addr
= NULL
;
1371 /* Add to the new list.. */
1372 if (new_email_addr
) {
1373 if (!(hil
= dict_find(nickserv_email_dict
, new_email_addr
, 0))) {
1374 hil
= calloc(1, sizeof(*hil
));
1375 hil
->tag
= strdup(new_email_addr
);
1376 handle_info_list_init(hil
);
1377 dict_insert(nickserv_email_dict
, hil
->tag
, hil
);
1379 handle_info_list_append(hil
, hi
);
1380 hi
->email_addr
= hil
->tag
;
1384 static NICKSERV_FUNC(cmd_register
)
1387 struct handle_info
*hi
;
1388 const char *email_addr
, *password
;
1389 char syncpass
[MD5_CRYPT_LENGTH
];
1390 int no_auth
, weblink
;
1392 if (checkDefCon(DEFCON_NO_NEW_NICKS
) && !IsOper(user
)) {
1393 reply("NSMSG_DEFCON_NO_NEW_NICKS", nickserv_conf
.disable_nicks
? "accounts" : "nicknames");
1397 if (!IsOper(user
) && !dict_size(nickserv_handle_dict
)) {
1398 /* Require the first handle registered to belong to someone +o. */
1399 reply("NSMSG_REQUIRE_OPER");
1403 if (user
->handle_info
) {
1404 reply("NSMSG_USE_RENAME", user
->handle_info
->handle
);
1408 if (IsRegistering(user
)) {
1409 reply("NSMSG_ALREADY_REGISTERING");
1413 if (IsStamped(user
)) {
1414 /* Unauthenticated users might still have been stamped
1415 previously and could therefore have a hidden host;
1416 do not allow them to register a new account. */
1417 reply("NSMSG_STAMPED_REGISTER");
1421 NICKSERV_MIN_PARMS((unsigned)3 + nickserv_conf
.email_required
);
1423 if(nickserv_conf
.force_handles_lowercase
)
1424 irc_strtolower(argv
[1]);
1425 if (!is_valid_handle(argv
[1])) {
1426 reply("NSMSG_BAD_HANDLE", argv
[1]);
1431 if ((argc
>= 4) && nickserv_conf
.email_enabled
) {
1432 struct handle_info_list
*hil
;
1435 /* Remember email address. */
1436 email_addr
= argv
[3];
1438 /* Check that the email address looks valid.. */
1439 if (!valid_email(email_addr
)) {
1440 reply("NSMSG_BAD_EMAIL_ADDR");
1444 /* .. and that we are allowed to send to it. */
1445 if ((str
= mail_prohibited_address(email_addr
))) {
1446 reply("NSMSG_EMAIL_PROHIBITED", email_addr
, str
);
1450 /* If we do email verify, make sure we don't spam the address. */
1451 if ((hil
= dict_find(nickserv_email_dict
, email_addr
, NULL
))) {
1453 for (nn
=0; nn
<hil
->used
; nn
++) {
1454 if (hil
->list
[nn
]->cookie
) {
1455 reply("NSMSG_EMAIL_UNACTIVATED");
1459 if (hil
->used
>= nickserv_conf
.handles_per_email
) {
1460 reply("NSMSG_EMAIL_OVERUSED");
1473 /* Webregister hack - send URL instead of IRC cookie
1476 if((argc
>= 5) && !strcmp(argv
[4],"WEBLINK"))
1480 if (!(hi
= nickserv_register(user
, user
, argv
[1], password
, no_auth
)))
1482 /* Add any masks they should get. */
1483 if (nickserv_conf
.default_hostmask
) {
1484 string_list_append(hi
->masks
, strdup("*@*"));
1486 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
1487 if (irc_in_addr_is_valid(user
->ip
) && !irc_pton(&ip
, NULL
, user
->hostname
))
1488 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_BYIP
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
1491 /* If they're the first to register, give them level 1000. */
1492 if (dict_size(nickserv_handle_dict
) == 1) {
1493 hi
->opserv_level
= 1000;
1494 reply("NSMSG_ROOT_HANDLE", argv
[1]);
1497 /* Set their email address. */
1500 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1502 if((rc
= ldap_do_modify(hi
->handle
, NULL
, email_addr
)) != LDAP_SUCCESS
) {
1503 /* Falied to update email in ldap, but still
1504 * updated it here.. what should we do? */
1505 reply("NSMSG_LDAP_FAIL_EMAIL", ldap_err2string(rc
));
1507 nickserv_set_email_addr(hi
, email_addr
);
1511 nickserv_set_email_addr(hi
, email_addr
);
1514 nickserv_set_email_addr(hi
, email_addr
);
1518 /* If they need to do email verification, tell them. */
1520 nickserv_make_cookie(user
, hi
, ACTIVATION
, hi
->passwd
, weblink
);
1522 /* Set registering flag.. */
1523 user
->modes
|= FLAGS_REGISTERING
;
1525 if (nickserv_conf
.sync_log
) {
1526 cryptpass(password
, syncpass
);
1528 * An 0 is only sent if theres no email address. Thios should only happen if email functions are
1529 * disabled which they wont be for us. Email Required MUST be set on if you are using this.
1532 SyncLog("REGISTER %s %s %s %s", hi
->handle
, syncpass
, email_addr
? email_addr
: "0", user
->info
);
1535 /* this wont work if email is required .. */
1536 process_adduser_pending(user
);
1541 static NICKSERV_FUNC(cmd_oregister
)
1543 struct userNode
*settee
= NULL
;
1544 struct handle_info
*hi
;
1545 char* account
= NULL
;
1551 NICKSERV_MIN_PARMS(2);
1555 if(nickserv_conf
.force_handles_lowercase
)
1556 irc_strtolower(account
);
1557 if (!is_valid_handle(argv
[1])) {
1558 reply("NSMSG_BAD_HANDLE", argv
[1]);
1561 if (nickserv_conf
.email_required
) {
1562 NICKSERV_MIN_PARMS(3);
1564 if (argc
> 4) {/* take: "acct pass email mask nick" or "acct pass email mask" or "acct pass email nick" */
1565 if (strchr(argv
[4], '@'))
1575 if (argc
> 3) {/* take: "account pass mask nick" or "account pass mask" or "account pass nick" */
1576 if (strchr(argv
[3], '@'))
1585 /* If they passed a nick, look for that user.. */
1586 if (nick
&& !(settee
= GetUserH(nick
))) {
1587 reply("MSG_NICK_UNKNOWN", argv
[4]);
1590 /* If the setee is already authed, we cant add a 2nd account for them.. */
1591 if (settee
&& settee
->handle_info
) {
1592 reply("NSMSG_USER_PREV_AUTH", settee
->nick
);
1595 /* If there is no default mask in the conf, and they didn't pass a mask,
1596 * but we did find a user by nick, generate the mask */
1598 if (nickserv_conf
.default_hostmask
)
1601 mask
= generate_hostmask(settee
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
1603 reply("NSMSG_REGISTER_BAD_NICKMASK");
1608 if (!(hi
= nickserv_register(user
, settee
, account
, pass
, 0))) {
1609 return 0; /* error reply handled by above */
1613 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1615 if((rc
= ldap_do_modify(hi
->handle
, NULL
, email
)) != LDAP_SUCCESS
) {
1616 /* Falied to update email in ldap, but still
1617 * updated it here.. what should we do? */
1618 reply("NSMSG_LDAP_FAIL_EMAIL", ldap_err2string(rc
));
1620 nickserv_set_email_addr(hi
, email
);
1624 nickserv_set_email_addr(hi
, email
);
1627 nickserv_set_email_addr(hi
, email
);
1631 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
1632 if (mask_canonicalized
)
1633 string_list_append(hi
->masks
, mask_canonicalized
);
1638 if (nickserv_conf
.sync_log
)
1639 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, email
? email
: "@", user
->info
); /* Send just @ for email if none */
1644 nickserv_ignore(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, char *mask
)
1647 struct userNode
*target
;
1648 char *new_mask
= strdup(pretty_mask(mask
));
1649 for (i
=0; i
<hi
->ignores
->used
; i
++) {
1650 if (!irccasecmp(new_mask
, hi
->ignores
->list
[i
])) {
1651 reply("NSMSG_ADDIGNORE_ALREADY", new_mask
);
1656 string_list_append(hi
->ignores
, new_mask
);
1657 reply("NSMSG_ADDIGNORE_SUCCESS", new_mask
);
1659 for (target
= hi
->users
; target
; target
= target
->next_authed
) {
1660 irc_silence(target
, new_mask
, 1);
1665 static NICKSERV_FUNC(cmd_addignore
)
1667 NICKSERV_MIN_PARMS(2);
1669 return nickserv_ignore(cmd
, user
, user
->handle_info
, argv
[1]);
1672 static NICKSERV_FUNC(cmd_oaddignore
)
1674 struct handle_info
*hi
;
1676 NICKSERV_MIN_PARMS(3);
1677 if (!(hi
= get_victim_oper(user
, argv
[1])))
1680 return nickserv_ignore(cmd
, user
, hi
, argv
[2]);
1684 nickserv_delignore(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, char *del_mask
)
1687 struct userNode
*target
;
1688 char *pmask
= strdup(pretty_mask(del_mask
));
1689 for (i
=0; i
<hi
->ignores
->used
; i
++) {
1690 if (!strcmp(pmask
, hi
->ignores
->list
[i
]) || !strcmp(del_mask
, hi
->ignores
->list
[i
])) {
1691 char *old_mask
= hi
->ignores
->list
[i
];
1692 hi
->ignores
->list
[i
] = hi
->ignores
->list
[--hi
->ignores
->used
];
1693 reply("NSMSG_DELMASK_SUCCESS", old_mask
);
1694 for (target
= hi
->users
; target
; target
= target
->next_authed
) {
1695 irc_silence(target
, old_mask
, 0);
1702 reply("NSMSG_DELMASK_NOT_FOUND");
1706 static NICKSERV_FUNC(cmd_delignore
)
1708 NICKSERV_MIN_PARMS(2);
1709 return nickserv_delignore(cmd
, user
, user
->handle_info
, argv
[1]);
1712 static NICKSERV_FUNC(cmd_odelignore
)
1714 struct handle_info
*hi
;
1715 NICKSERV_MIN_PARMS(3);
1716 if (!(hi
= get_victim_oper(user
, argv
[1])))
1718 return nickserv_delignore(cmd
, user
, hi
, argv
[2]);
1721 static NICKSERV_FUNC(cmd_handleinfo
)
1724 unsigned int i
, pos
=0, herelen
;
1725 struct userNode
*target
, *next_un
;
1726 struct handle_info
*hi
;
1727 const char *nsmsg_none
;
1730 if (!(hi
= user
->handle_info
)) {
1731 reply("NSMSG_MUST_AUTH");
1734 } else if (!(hi
= modcmd_get_handle_info(user
, argv
[1]))) {
1738 nsmsg_none
= handle_find_message(hi
, "MSG_NONE");
1739 reply("NSMSG_HANDLEINFO_ON", hi
->handle
);
1741 reply("NSMSG_HANDLEINFO_REGGED", ctime(&hi
->registered
));
1744 intervalString(buff
, now
- hi
->lastseen
, user
->handle_info
);
1745 reply("NSMSG_HANDLEINFO_LASTSEEN", buff
);
1747 reply("NSMSG_HANDLEINFO_LASTSEEN_NOW");
1750 reply("NSMSG_HANDLEINFO_INFOLINE", (hi
->infoline
? hi
->infoline
: nsmsg_none
));
1751 if (HANDLE_FLAGGED(hi
, FROZEN
))
1752 reply("NSMSG_HANDLEINFO_VACATION");
1754 if (oper_has_access(user
, cmd
->parent
->bot
, 0, 1)) {
1755 struct do_not_register
*dnr
;
1756 if ((dnr
= chanserv_is_dnr(NULL
, hi
)))
1757 reply("NSMSG_HANDLEINFO_DNR", dnr
->setter
, dnr
->reason
);
1758 if ((user
->handle_info
->opserv_level
< 900) && !oper_outranks(user
, hi
))
1760 } else if (hi
!= user
->handle_info
) {
1761 reply("NSMSG_HANDLEINFO_END");
1766 reply("NSMSG_HANDLEINFO_KARMA", hi
->karma
);
1768 if (nickserv_conf
.email_enabled
)
1769 reply("NSMSG_HANDLEINFO_EMAIL_ADDR", visible_email_addr(user
, hi
));
1773 switch (hi
->cookie
->type
) {
1774 case ACTIVATION
: type
= "NSMSG_HANDLEINFO_COOKIE_ACTIVATION"; break;
1775 case PASSWORD_CHANGE
: type
= "NSMSG_HANDLEINFO_COOKIE_PASSWORD"; break;
1776 case EMAIL_CHANGE
: type
= "NSMSG_HANDLEINFO_COOKIE_EMAIL"; break;
1777 case ALLOWAUTH
: type
= "NSMSG_HANDLEINFO_COOKIE_ALLOWAUTH"; break;
1778 default: type
= "NSMSG_HANDLEINFO_COOKIE_UNKNOWN"; break;
1781 if (IsOper(user
) && (hi
->cookie
->type
== EMAIL_CHANGE
))
1782 reply("NSMSG_HANDLEINFO_COOKIE_EMAIL_DATA", hi
->cookie
->data
);
1786 unsigned long flen
= 1;
1787 char flags
[34]; /* 32 bits possible plus '+' and '\0' */
1789 for (i
=0, flen
=1; handle_flags
[i
]; i
++)
1790 if (hi
->flags
& 1 << i
)
1791 flags
[flen
++] = handle_flags
[i
];
1793 reply("NSMSG_HANDLEINFO_FLAGS", flags
);
1795 reply("NSMSG_HANDLEINFO_FLAGS", nsmsg_none
);
1798 if (HANDLE_FLAGGED(hi
, SUPPORT_HELPER
)
1799 || HANDLE_FLAGGED(hi
, NETWORK_HELPER
)
1800 || (hi
->opserv_level
> 0)) {
1801 reply("NSMSG_HANDLEINFO_EPITHET", (hi
->epithet
? hi
->epithet
: nsmsg_none
));
1804 if (IsHelping(user
) || IsOper(user
))
1809 strftime(date
, 64, "%b %d %Y", localtime(&hi
->note
->date
));
1810 reply("NSMSG_HANDLEINFO_NOTE", hi
->note
->setter
, date
, hi
->note
->note
);
1815 reply("NSMSG_HANDLEINFO_FAKEHOST", (hi
->fakehost
? hi
->fakehost
: handle_find_message(hi
, "MSG_NONE")));
1817 if (hi
->last_quit_host
[0])
1818 reply("NSMSG_HANDLEINFO_LAST_HOST", hi
->last_quit_host
);
1820 reply("NSMSG_HANDLEINFO_LAST_HOST_UNKNOWN");
1822 if (nickserv_conf
.disable_nicks
) {
1823 /* nicks disabled; don't show anything about registered nicks */
1824 } else if (hi
->nicks
) {
1825 struct nick_info
*ni
, *next_ni
;
1826 for (ni
= hi
->nicks
; ni
; ni
= next_ni
) {
1827 herelen
= strlen(ni
->nick
);
1828 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1830 goto print_nicks_buff
;
1834 memcpy(buff
+pos
, ni
->nick
, herelen
);
1835 pos
+= herelen
; buff
[pos
++] = ' ';
1839 reply("NSMSG_HANDLEINFO_NICKS", buff
);
1844 reply("NSMSG_HANDLEINFO_NICKS", nsmsg_none
);
1847 if (hi
->masks
->used
) {
1848 for (i
=0; i
< hi
->masks
->used
; i
++) {
1849 herelen
= strlen(hi
->masks
->list
[i
]);
1850 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1852 goto print_mask_buff
;
1854 memcpy(buff
+pos
, hi
->masks
->list
[i
], herelen
);
1855 pos
+= herelen
; buff
[pos
++] = ' ';
1856 if (i
+1 == hi
->masks
->used
) {
1859 reply("NSMSG_HANDLEINFO_MASKS", buff
);
1864 reply("NSMSG_HANDLEINFO_MASKS", nsmsg_none
);
1867 if (hi
->sslfps
->used
) {
1868 for (i
=0; i
< hi
->sslfps
->used
; i
++) {
1869 herelen
= strlen(hi
->sslfps
->list
[i
]);
1870 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1872 goto print_sslfp_buff
;
1874 memcpy(buff
+pos
, hi
->sslfps
->list
[i
], herelen
);
1875 pos
+= herelen
; buff
[pos
++] = ' ';
1876 if (i
+1 == hi
->sslfps
->used
) {
1879 reply("NSMSG_HANDLEINFO_SSLFPS", buff
);
1884 reply("NSMSG_HANDLEINFO_SSLFPS", nsmsg_none
);
1887 if (hi
->ignores
->used
) {
1888 for (i
=0; i
< hi
->ignores
->used
; i
++) {
1889 herelen
= strlen(hi
->ignores
->list
[i
]);
1890 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1892 goto print_ignore_buff
;
1894 memcpy(buff
+pos
, hi
->ignores
->list
[i
], herelen
);
1895 pos
+= herelen
; buff
[pos
++] = ' ';
1896 if (i
+1 == hi
->ignores
->used
) {
1899 reply("NSMSG_HANDLEINFO_IGNORES", buff
);
1904 reply("NSMSG_HANDLEINFO_IGNORES", nsmsg_none
);
1908 struct userData
*chan
, *next
;
1911 for (chan
= hi
->channels
; chan
; chan
= next
) {
1912 next
= chan
->u_next
;
1913 name
= chan
->channel
->channel
->name
;
1914 herelen
= strlen(name
);
1915 if (pos
+ herelen
+ 7 > ArrayLength(buff
)) {
1917 goto print_chans_buff
;
1919 if (IsUserSuspended(chan
))
1921 pos
+= sprintf(buff
+pos
, "%s:%s ", user_level_name_from_level(chan
->access
), name
);
1925 reply("NSMSG_HANDLEINFO_CHANNELS", buff
);
1930 reply("NSMSG_HANDLEINFO_CHANNELS", nsmsg_none
);
1933 for (target
= hi
->users
; target
; target
= next_un
) {
1934 herelen
= strlen(target
->nick
);
1935 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1937 goto print_cnick_buff
;
1939 next_un
= target
->next_authed
;
1941 memcpy(buff
+pos
, target
->nick
, herelen
);
1942 pos
+= herelen
; buff
[pos
++] = ' ';
1946 reply("NSMSG_HANDLEINFO_CURRENT", buff
);
1951 reply("NSMSG_HANDLEINFO_END");
1952 return 1 | ((hi
!= user
->handle_info
) ? CMD_LOG_STAFF
: 0);
1955 static NICKSERV_FUNC(cmd_userinfo
)
1957 struct userNode
*target
;
1959 NICKSERV_MIN_PARMS(2);
1960 if (!(target
= GetUserH(argv
[1]))) {
1961 reply("MSG_NICK_UNKNOWN", argv
[1]);
1964 if (target
->handle_info
)
1965 reply("NSMSG_USERINFO_AUTHED_AS", target
->nick
, target
->handle_info
->handle
);
1967 reply("NSMSG_USERINFO_NOT_AUTHED", target
->nick
);
1971 static NICKSERV_FUNC(cmd_nickinfo
)
1973 struct nick_info
*ni
;
1976 NICKSERV_MIN_PARMS(2);
1977 if (!(ni
= get_nick_info(argv
[1]))) {
1978 reply("MSG_NICK_UNKNOWN", argv
[1]);
1982 reply("NSMSG_NICKINFO_ON", ni
->nick
);
1984 reply("NSMSG_NICKINFO_REGGED", ctime(&ni
->registered
));
1986 if (!GetUserH(ni
->nick
)) {
1987 intervalString(buff
, now
- ni
->lastseen
, user
->handle_info
);
1988 reply("NSMSG_NICKINFO_LASTSEEN", buff
);
1990 reply("NSMSG_NICKINFO_LASTSEEN_NOW");
1993 reply("NSMSG_NICKINFO_OWNER", ni
->owner
->handle
);
1995 reply("NSMSG_NICKINFO_END");
2000 static NICKSERV_FUNC(cmd_rename_handle
)
2002 struct handle_info
*hi
;
2003 struct userNode
*uNode
;
2007 NICKSERV_MIN_PARMS(3);
2008 if(nickserv_conf
.force_handles_lowercase
)
2009 irc_strtolower(argv
[2]);
2010 if (!(hi
= get_victim_oper(user
, argv
[1])))
2012 if (!is_valid_handle(argv
[2])) {
2013 reply("NSMSG_FAIL_RENAME", argv
[1], argv
[2]);
2016 if (get_handle_info(argv
[2])) {
2017 reply("NSMSG_HANDLE_EXISTS", argv
[2]);
2020 if(strlen(argv
[2]) > 30)
2022 reply("NMSG_HANDLE_TOLONG", argv
[2], 30);
2026 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2028 if( (rc
= ldap_rename_account(hi
->handle
, argv
[2])) != LDAP_SUCCESS
) {
2029 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2035 dict_remove2(nickserv_handle_dict
, old_handle
= hi
->handle
, 1);
2036 hi
->handle
= strdup(argv
[2]);
2037 dict_insert(nickserv_handle_dict
, hi
->handle
, hi
);
2038 for (nn
=0; nn
<rf_list_used
; nn
++)
2039 rf_list
[nn
](hi
, old_handle
, rf_list_extra
[nn
]);
2041 if (nickserv_conf
.sync_log
) {
2042 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
2043 irc_rename(uNode
, hi
->handle
);
2045 SyncLog("RENAME %s %s", old_handle
, hi
->handle
);
2048 reply("NSMSG_HANDLE_CHANGED", old_handle
, hi
->handle
);
2049 global_message_args(MESSAGE_RECIPIENT_OPERS
, "NSMSG_ACCOUNT_RENAMED",
2050 user
->handle_info
->handle
, old_handle
, hi
->handle
);
2056 static failpw_func_t
*failpw_func_list
;
2057 static void **failpw_func_list_extra
;
2058 static unsigned int failpw_func_size
= 0, failpw_func_used
= 0;
2061 reg_failpw_func(failpw_func_t func
, void *extra
)
2063 if (failpw_func_used
== failpw_func_size
) {
2064 if (failpw_func_size
) {
2065 failpw_func_size
<<= 1;
2066 failpw_func_list
= realloc(failpw_func_list
, failpw_func_size
*sizeof(failpw_func_t
));
2067 failpw_func_list_extra
= realloc(failpw_func_list_extra
, failpw_func_size
*sizeof(void*));
2069 failpw_func_size
= 8;
2070 failpw_func_list
= malloc(failpw_func_size
*sizeof(failpw_func_t
));
2071 failpw_func_list_extra
= malloc(failpw_func_size
*sizeof(void*));
2074 failpw_func_list
[failpw_func_used
] = func
;
2075 failpw_func_list_extra
[failpw_func_used
++] = extra
;
2079 * Return hi if the handle/pass pair matches, NULL if it doesnt.
2081 * called by nefariouses enhanced AC login-on-connect code
2084 struct handle_info
*loc_auth(char *sslfp
, char *handle
, char *password
, char *userhost
)
2086 int wildmask
= 0, auth
= 0;
2087 int used
, maxlogins
;
2089 struct handle_info
*hi
;
2090 struct userNode
*other
;
2092 int ldap_result
= LDAP_SUCCESS
;
2096 hi
= dict_find(nickserv_handle_dict
, handle
, NULL
);
2099 if (nickserv_conf
.ldap_enable
) {
2100 ldap_result
= ldap_check_auth(handle
, password
);
2101 if (!hi
&& (ldap_result
!= LDAP_SUCCESS
))
2103 if (ldap_result
== LDAP_SUCCESS
) {
2104 /* Mark auth as successful */
2108 if (!hi
&& (ldap_result
== LDAP_SUCCESS
) && nickserv_conf
.ldap_autocreate
) {
2109 /* user not found, but authed to ldap successfully..
2110 * create the account.
2115 /* Add a *@* mask */
2116 /* TODO if userhost is not null, build mask based on that. */
2117 if(nickserv_conf
.default_hostmask
)
2120 return NULL
; /* They dont have a *@* mask so they can't loc */
2122 if(!(hi
= nickserv_register(NULL
, NULL
, handle
, password
, 0))) {
2123 return 0; /* couldn't add the user for some reason */
2126 if((rc
= ldap_get_user_info(handle
, &email
) != LDAP_SUCCESS
))
2128 if(nickserv_conf
.email_required
) {
2133 nickserv_set_email_addr(hi
, email
);
2137 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
2138 string_list_append(hi
->masks
, mask_canonicalized
);
2140 if(nickserv_conf
.sync_log
)
2141 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, "@", handle
);
2146 /* hi should now be a valid handle, if not return NULL */
2151 if (password
&& *password
&& !nickserv_conf
.ldap_enable
) {
2153 if (password
&& *password
) {
2155 if (checkpass(password
, hi
->passwd
))
2159 if (!auth
&& sslfp
&& *sslfp
&& hi
->sslfps
->used
) {
2160 /* If any SSL fingerprint matches, allow it. */
2161 for (ii
=0; ii
<hi
->sslfps
->used
; ii
++) {
2162 if (!irccasecmp(sslfp
, hi
->sslfps
->list
[ii
])) {
2169 /* Auth should have succeeded by this point */
2173 /* We don't know the users hostname, or anything because they
2174 * havn't registered yet. So we can only allow LOC if your
2175 * account has *@* as a hostmask.
2177 * UPDATE: New nefarious LOC supports u@h
2187 buf
= strdup(userhost
);
2188 ident
= mysep(&buf
, "@");
2189 realhost
= mysep(&buf
, ":");
2190 ip
= mysep(&buf
, ":");
2191 if(!ip
|| !realhost
|| !ident
) {
2193 return NULL
; /* Invalid AC request, just quit */
2195 uh
= malloc(strlen(userhost
));
2196 ui
= malloc(strlen(userhost
));
2197 sprintf(uh
, "%s@%s", ident
, realhost
);
2198 sprintf(ui
, "%s@%s", ident
, ip
);
2199 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
2201 if(match_ircglob(uh
, hi
->masks
->list
[ii
])
2202 || match_ircglob(ui
, hi
->masks
->list
[ii
]))
2214 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
2216 if (!strcmp(hi
->masks
->list
[ii
], "*@*"))
2226 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2230 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
2231 for (used
= 0, other
= hi
->users
; other
; other
= other
->next_authed
) {
2232 if (++used
>= maxlogins
) {
2236 /* TODO - Add LOGGING to this function so LOC's are logged.. */
2240 static NICKSERV_FUNC(cmd_auth
)
2242 int pw_arg
, used
, maxlogins
;
2243 struct handle_info
*hi
;
2246 struct userNode
*other
;
2248 int ldap_result
= LDAP_OTHER
;
2252 if (user
->handle_info
) {
2253 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2256 if (IsStamped(user
)) {
2257 /* Unauthenticated users might still have been stamped
2258 previously and could therefore have a hidden host;
2259 do not allow them to authenticate. */
2260 reply("NSMSG_STAMPED_AUTH");
2267 hi
= dict_find(nickserv_handle_dict
, argv
[1], NULL
);
2268 } else if (argc
== 2) {
2271 if (nickserv_conf
.disable_nicks
) {
2272 hi
= get_handle_info(user
->nick
);
2274 /* try to look up their handle from their nick */
2275 /* TODO: handle ldap auth on nickserv style networks, too */
2276 struct nick_info
*ni
;
2277 ni
= get_nick_info(user
->nick
);
2279 reply("NSMSG_NICK_NOT_REGISTERED", user
->nick
);
2285 handle
= hi
->handle
;
2287 handle
= user
->nick
;
2290 reply("MSG_MISSING_PARAMS", argv
[0]);
2291 svccmd_send_help_brief(user
, nickserv
, cmd
);
2296 if(strchr(argv
[1], '<') || strchr(handle
, '>')) {
2297 reply("NSMSG_NO_ANGLEBRACKETS");
2300 if (!is_valid_handle(handle
)) {
2301 reply("NSMSG_BAD_HANDLE", handle
);
2305 if(nickserv_conf
.ldap_enable
) {
2306 ldap_result
= ldap_check_auth(handle
, passwd
);
2307 /* Get the users email address and update it */
2308 if(ldap_result
== LDAP_SUCCESS
) {
2310 if((rc
= ldap_get_user_info(handle
, &email
) != LDAP_SUCCESS
))
2312 if(nickserv_conf
.email_required
) {
2313 reply("NSMSG_LDAP_FAIL_GET_EMAIL", ldap_err2string(rc
));
2318 else if(ldap_result
!= LDAP_INVALID_CREDENTIALS
) {
2319 reply("NSMSG_LDAP_FAIL", ldap_err2string(ldap_result
));
2327 if(nickserv_conf
.ldap_enable
&& ldap_result
== LDAP_SUCCESS
&& nickserv_conf
.ldap_autocreate
) {
2328 /* user not found, but authed to ldap successfully..
2329 * create the account.
2332 if(!(hi
= nickserv_register(user
, user
, argv
[1], argv
[2], 0))) {
2333 reply("NSMSG_UNABLE_TO_ADD");
2334 return 0; /* couldn't add the user for some reason */
2336 /* Add a *@* mask */
2337 if(nickserv_conf
.default_hostmask
)
2340 mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2343 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
2344 string_list_append(hi
->masks
, mask_canonicalized
);
2347 nickserv_set_email_addr(hi
, email
);
2350 if(nickserv_conf
.sync_log
)
2351 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, email
? email
: "@", user
->info
);
2355 reply("NSMSG_HANDLE_NOT_FOUND");
2361 /* Responses from here on look up the language used by the handle they asked about. */
2362 if (!valid_user_for(user
, hi
)) {
2363 if (hi
->email_addr
&& nickserv_conf
.email_enabled
)
2364 send_message_type(4, user
, cmd
->parent
->bot
,
2365 handle_find_message(hi
, "NSMSG_USE_AUTHCOOKIE"),
2368 send_message_type(4, user
, cmd
->parent
->bot
,
2369 handle_find_message(hi
, "NSMSG_HOSTMASK_INVALID"),
2371 argv
[pw_arg
] = "BADMASK";
2375 if(( ( nickserv_conf
.ldap_enable
&& ldap_result
== LDAP_INVALID_CREDENTIALS
) ||
2376 ( (!nickserv_conf
.ldap_enable
) && (!checkpass(passwd
, hi
->passwd
)) ) ) && !valid_user_sslfp(user
, hi
)) {
2378 if (!checkpass(passwd
, hi
->passwd
) && !valid_user_sslfp(user
, hi
)) {
2381 send_message_type(4, user
, cmd
->parent
->bot
,
2382 handle_find_message(hi
, "NSMSG_PASSWORD_INVALID"));
2383 argv
[pw_arg
] = "BADPASS";
2384 for (n
=0; n
<failpw_func_used
; n
++)
2385 failpw_func_list
[n
](user
, hi
, failpw_func_list_extra
[n
]);
2386 if (nickserv_conf
.autogag_enabled
) {
2387 if (!user
->auth_policer
.params
) {
2388 user
->auth_policer
.last_req
= now
;
2389 user
->auth_policer
.params
= nickserv_conf
.auth_policer_params
;
2391 if (!policer_conforms(&user
->auth_policer
, now
, 1.0)) {
2393 hostmask
= generate_hostmask(user
, GENMASK_STRICT_HOST
|GENMASK_BYIP
|GENMASK_NO_HIDING
);
2394 log_module(NS_LOG
, LOG_INFO
, "%s auto-gagged for repeated password guessing.", hostmask
);
2395 gag_create(hostmask
, nickserv
->nick
, "Repeated password guessing.", now
+nickserv_conf
.autogag_duration
);
2397 argv
[pw_arg
] = "GAGGED";
2402 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2403 send_message_type(4, user
, cmd
->parent
->bot
,
2404 handle_find_message(hi
, "NSMSG_HANDLE_SUSPENDED"));
2405 argv
[pw_arg
] = "SUSPENDED";
2408 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
2409 for (used
= 0, other
= hi
->users
; other
; other
= other
->next_authed
) {
2410 if (++used
>= maxlogins
) {
2411 send_message_type(4, user
, cmd
->parent
->bot
,
2412 handle_find_message(hi
, "NSMSG_MAX_LOGINS"),
2414 argv
[pw_arg
] = "MAXLOGINS";
2419 set_user_handle_info(user
, hi
, 1);
2420 if (nickserv_conf
.email_required
&& !hi
->email_addr
)
2421 reply("NSMSG_PLEASE_SET_EMAIL");
2422 if (!is_secure_password(hi
->handle
, passwd
, NULL
))
2423 reply("NSMSG_WEAK_PASSWORD");
2424 if (hi
->passwd
[0] != '$')
2425 cryptpass(passwd
, hi
->passwd
);
2427 /* If a channel was waiting for this user to auth,
2428 * finish adding them */
2429 process_adduser_pending(user
);
2431 reply("NSMSG_AUTH_SUCCESS");
2434 /* Set +x if autohide is on */
2435 if(HANDLE_FLAGGED(hi
, AUTOHIDE
))
2436 irc_umode(user
, "+x");
2438 if (!hi
->masks
->used
) {
2440 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
2441 if (irc_in_addr_is_valid(user
->ip
) && irc_pton(&ip
, NULL
, user
->hostname
))
2442 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_BYIP
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
2445 /* Wipe out the pass for the logs */
2446 argv
[pw_arg
] = "****";
2450 static allowauth_func_t
*allowauth_func_list
;
2451 static void **allowauth_func_list_extra
;
2452 static unsigned int allowauth_func_size
= 0, allowauth_func_used
= 0;
2455 reg_allowauth_func(allowauth_func_t func
, void *extra
)
2457 if (allowauth_func_used
== allowauth_func_size
) {
2458 if (allowauth_func_size
) {
2459 allowauth_func_size
<<= 1;
2460 allowauth_func_list
= realloc(allowauth_func_list
, allowauth_func_size
*sizeof(allowauth_func_t
));
2461 allowauth_func_list_extra
= realloc(allowauth_func_list_extra
, allowauth_func_size
*sizeof(void*));
2463 allowauth_func_size
= 8;
2464 allowauth_func_list
= malloc(allowauth_func_size
*sizeof(allowauth_func_t
));
2465 allowauth_func_list_extra
= malloc(allowauth_func_size
*sizeof(void*));
2468 allowauth_func_list
[allowauth_func_used
] = func
;
2469 allowauth_func_list_extra
[allowauth_func_used
++] = extra
;
2472 static NICKSERV_FUNC(cmd_allowauth
)
2474 struct userNode
*target
;
2475 struct handle_info
*hi
;
2478 NICKSERV_MIN_PARMS(2);
2479 if (!(target
= GetUserH(argv
[1]))) {
2480 reply("MSG_NICK_UNKNOWN", argv
[1]);
2483 if (target
->handle_info
) {
2484 reply("NSMSG_USER_PREV_AUTH", target
->nick
);
2487 if (IsStamped(target
)) {
2488 /* Unauthenticated users might still have been stamped
2489 previously and could therefore have a hidden host;
2490 do not allow them to authenticate to an account. */
2491 reply("NSMSG_USER_PREV_STAMP", target
->nick
);
2496 else if (!(hi
= get_handle_info(argv
[2]))) {
2497 reply("MSG_HANDLE_UNKNOWN", argv
[2]);
2501 if (hi
->opserv_level
> user
->handle_info
->opserv_level
) {
2502 reply("MSG_USER_OUTRANKED", hi
->handle
);
2505 if (((hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
))
2506 || (hi
->opserv_level
> 0))
2507 && ((argc
< 4) || irccasecmp(argv
[3], "staff"))) {
2508 reply("NSMSG_ALLOWAUTH_STAFF", hi
->handle
);
2511 dict_insert(nickserv_allow_auth_dict
, target
->nick
, hi
);
2512 reply("NSMSG_AUTH_ALLOWED", target
->nick
, hi
->handle
);
2513 send_message(target
, nickserv
, "NSMSG_AUTH_ALLOWED_MSG", hi
->handle
, hi
->handle
);
2514 if (nickserv_conf
.email_enabled
)
2515 send_message(target
, nickserv
, "NSMSG_AUTH_ALLOWED_EMAIL");
2517 if (dict_remove(nickserv_allow_auth_dict
, target
->nick
))
2518 reply("NSMSG_AUTH_NORMAL_ONLY", target
->nick
);
2520 reply("NSMSG_AUTH_UNSPECIAL", target
->nick
);
2522 for (n
=0; n
<allowauth_func_used
; n
++)
2523 allowauth_func_list
[n
](user
, target
, hi
, allowauth_func_list_extra
[n
]);
2527 static NICKSERV_FUNC(cmd_authcookie
)
2529 struct handle_info
*hi
;
2531 NICKSERV_MIN_PARMS(2);
2532 if (user
->handle_info
) {
2533 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2536 if (IsStamped(user
)) {
2537 /* Unauthenticated users might still have been stamped
2538 previously and could therefore have a hidden host;
2539 do not allow them to authenticate to an account. */
2540 reply("NSMSG_STAMPED_AUTHCOOKIE");
2543 if (!(hi
= get_handle_info(argv
[1]))) {
2544 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2547 if (!hi
->email_addr
) {
2548 reply("MSG_SET_EMAIL_ADDR");
2551 nickserv_make_cookie(user
, hi
, ALLOWAUTH
, NULL
, 0);
2555 static NICKSERV_FUNC(cmd_delcookie
)
2557 struct handle_info
*hi
;
2559 hi
= user
->handle_info
;
2561 reply("NSMSG_NO_COOKIE");
2564 switch (hi
->cookie
->type
) {
2567 reply("NSMSG_MUST_TIME_OUT");
2570 nickserv_eat_cookie(hi
->cookie
);
2571 reply("NSMSG_ATE_COOKIE");
2577 static NICKSERV_FUNC(cmd_odelcookie
)
2579 struct handle_info
*hi
;
2581 NICKSERV_MIN_PARMS(2);
2583 if (!(hi
= get_victim_oper(user
, argv
[1])))
2587 reply("NSMSG_NO_COOKIE_FOREIGN", hi
->handle
);
2591 switch (hi
->cookie
->type
) {
2593 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2595 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2597 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2598 /* Falied to update password in ldap, but still
2599 * updated it here.. what should we do? */
2600 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2605 if (nickserv_conf
.sync_log
)
2606 SyncLog("ACCOUNTACC %s", hi
->handle
);
2608 case PASSWORD_CHANGE
:
2615 reply("NSMSG_BAD_COOKIE_TYPE", hi
->cookie
->type
);
2616 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d for account %s.", hi
->cookie
->type
, hi
->handle
);
2620 nickserv_eat_cookie(hi
->cookie
);
2621 reply("NSMSG_ATE_FOREIGN_COOKIE", hi
->handle
);
2626 static NICKSERV_FUNC(cmd_resetpass
)
2628 struct handle_info
*hi
;
2629 char crypted
[MD5_CRYPT_LENGTH
];
2632 NICKSERV_MIN_PARMS(3);
2633 if(argc
>= 4 && !strcmp(argv
[3], "WEBLINK"))
2637 if (user
->handle_info
) {
2638 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2641 if (IsStamped(user
)) {
2642 /* Unauthenticated users might still have been stamped
2643 previously and could therefore have a hidden host;
2644 do not allow them to activate an account. */
2645 reply("NSMSG_STAMPED_RESETPASS");
2648 if (!(hi
= get_handle_info(argv
[1]))) {
2649 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2652 if (!hi
->email_addr
) {
2653 reply("MSG_SET_EMAIL_ADDR");
2656 cryptpass(argv
[2], crypted
);
2658 nickserv_make_cookie(user
, hi
, PASSWORD_CHANGE
, crypted
, weblink
);
2662 static NICKSERV_FUNC(cmd_cookie
)
2664 struct handle_info
*hi
;
2667 if ((argc
== 2) && (hi
= user
->handle_info
) && hi
->cookie
&& (hi
->cookie
->type
== EMAIL_CHANGE
)) {
2670 NICKSERV_MIN_PARMS(3);
2671 if (!(hi
= get_handle_info(argv
[1]))) {
2672 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2678 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2679 reply("NSMSG_HANDLE_SUSPENDED");
2684 reply("NSMSG_NO_COOKIE");
2688 /* Check validity of operation before comparing cookie to
2689 * prohibit guessing by authed users. */
2690 if (user
->handle_info
2691 && (hi
->cookie
->type
!= EMAIL_CHANGE
)
2692 && (hi
->cookie
->type
!= PASSWORD_CHANGE
)) {
2693 reply("NSMSG_CANNOT_COOKIE");
2697 if (strcmp(cookie
, hi
->cookie
->cookie
)) {
2698 reply("NSMSG_BAD_COOKIE");
2702 switch (hi
->cookie
->type
) {
2705 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2707 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2708 /* Falied to update email in ldap, but still
2709 * updated it here.. what should we do? */
2710 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2715 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2716 set_user_handle_info(user
, hi
, 1);
2717 reply("NSMSG_HANDLE_ACTIVATED");
2718 if (nickserv_conf
.sync_log
)
2719 SyncLog("ACCOUNTACC %s", hi
->handle
);
2721 case PASSWORD_CHANGE
:
2723 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2725 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2726 /* Falied to update email in ldap, but still
2727 * updated it here.. what should we do? */
2728 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2733 set_user_handle_info(user
, hi
, 1);
2734 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2735 reply("NSMSG_PASSWORD_CHANGED");
2736 if (nickserv_conf
.sync_log
)
2737 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
2741 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2743 if((rc
= ldap_do_modify(hi
->handle
, NULL
, hi
->cookie
->data
)) != LDAP_SUCCESS
) {
2744 /* Falied to update email in ldap, but still
2745 * updated it here.. what should we do? */
2746 reply("NSMSG_LDAP_FAIL_SEND_EMAIL", ldap_err2string(rc
));
2751 if (!hi
->email_addr
&& nickserv_conf
.sync_log
) {
2753 * This should only happen if an OREGISTER was sent. Require
2754 * email must be enabled! - SiRVulcaN
2756 if (nickserv_conf
.sync_log
)
2757 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, hi
->cookie
->data
, user
->info
);
2760 nickserv_set_email_addr(hi
, hi
->cookie
->data
);
2761 reply("NSMSG_EMAIL_CHANGED");
2762 if (nickserv_conf
.sync_log
)
2763 SyncLog("EMAILCHANGE %s %s", hi
->handle
, hi
->cookie
->data
);
2766 char *mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2767 set_user_handle_info(user
, hi
, 1);
2768 nickserv_addmask(user
, hi
, mask
);
2769 reply("NSMSG_AUTH_SUCCESS");
2774 reply("NSMSG_BAD_COOKIE_TYPE", hi
->cookie
->type
);
2775 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d for account %s.", hi
->cookie
->type
, hi
->handle
);
2779 nickserv_eat_cookie(hi
->cookie
);
2781 process_adduser_pending(user
);
2786 static NICKSERV_FUNC(cmd_oregnick
) {
2788 struct handle_info
*target
;
2789 struct nick_info
*ni
;
2791 NICKSERV_MIN_PARMS(3);
2792 if (!(target
= modcmd_get_handle_info(user
, argv
[1])))
2795 if (!is_registerable_nick(nick
)) {
2796 reply("NSMSG_BAD_NICK", nick
);
2799 ni
= dict_find(nickserv_nick_dict
, nick
, NULL
);
2801 reply("NSMSG_NICK_EXISTS", nick
);
2804 register_nick(nick
, target
);
2805 reply("NSMSG_OREGNICK_SUCCESS", nick
, target
->handle
);
2809 static NICKSERV_FUNC(cmd_regnick
) {
2811 struct nick_info
*ni
;
2813 if (!is_registerable_nick(user
->nick
)) {
2814 reply("NSMSG_BAD_NICK", user
->nick
);
2817 /* count their nicks, see if it's too many */
2818 for (n
=0,ni
=user
->handle_info
->nicks
; ni
; n
++,ni
=ni
->next
) ;
2819 if (n
>= nickserv_conf
.nicks_per_handle
) {
2820 reply("NSMSG_TOO_MANY_NICKS");
2823 ni
= dict_find(nickserv_nick_dict
, user
->nick
, NULL
);
2825 reply("NSMSG_NICK_EXISTS", user
->nick
);
2828 register_nick(user
->nick
, user
->handle_info
);
2829 reply("NSMSG_REGNICK_SUCCESS", user
->nick
);
2833 static NICKSERV_FUNC(cmd_pass
)
2835 struct handle_info
*hi
;
2836 char *old_pass
, *new_pass
;
2837 char crypted
[MD5_CRYPT_LENGTH
+1];
2842 NICKSERV_MIN_PARMS(3);
2843 hi
= user
->handle_info
;
2847 if (!is_secure_password(hi
->handle
, new_pass
, user
)) return 0;
2850 if(nickserv_conf
.ldap_enable
) {
2851 ldap_result
= ldap_check_auth(hi
->handle
, old_pass
);
2852 if(ldap_result
!= LDAP_SUCCESS
) {
2853 if(ldap_result
== LDAP_INVALID_CREDENTIALS
)
2854 reply("NSMSG_PASSWORD_INVALID");
2856 reply("NSMSG_LDAP_FAIL", ldap_err2string(ldap_result
));
2861 if (!checkpass(old_pass
, hi
->passwd
)) {
2862 argv
[1] = "BADPASS";
2863 reply("NSMSG_PASSWORD_INVALID");
2866 cryptpass(new_pass
, crypted
);
2868 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2870 if((rc
= ldap_do_modify(hi
->handle
, crypted
, NULL
)) != LDAP_SUCCESS
) {
2871 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2876 //cryptpass(new_pass, hi->passwd);
2877 strcpy(hi
->passwd
, crypted
);
2878 if (nickserv_conf
.sync_log
)
2879 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
2881 reply("NSMSG_PASS_SUCCESS");
2886 nickserv_addmask(struct userNode
*user
, struct handle_info
*hi
, const char *mask
)
2889 char *new_mask
= canonicalize_hostmask(strdup(mask
));
2890 for (i
=0; i
<hi
->masks
->used
; i
++) {
2891 if (!irccasecmp(new_mask
, hi
->masks
->list
[i
])) {
2892 send_message(user
, nickserv
, "NSMSG_ADDMASK_ALREADY", new_mask
);
2897 string_list_append(hi
->masks
, new_mask
);
2898 send_message(user
, nickserv
, "NSMSG_ADDMASK_SUCCESS", new_mask
);
2902 static NICKSERV_FUNC(cmd_addmask
)
2905 char *mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2906 int res
= nickserv_addmask(user
, user
->handle_info
, mask
);
2910 if (!is_gline(argv
[1])) {
2911 reply("NSMSG_MASK_INVALID", argv
[1]);
2914 return nickserv_addmask(user
, user
->handle_info
, argv
[1]);
2918 static NICKSERV_FUNC(cmd_oaddmask
)
2920 struct handle_info
*hi
;
2922 NICKSERV_MIN_PARMS(3);
2923 if (!(hi
= get_victim_oper(user
, argv
[1])))
2925 return nickserv_addmask(user
, hi
, argv
[2]);
2929 nickserv_delmask(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, const char *del_mask
, int force
)
2932 for (i
=0; i
<hi
->masks
->used
; i
++) {
2933 if (!strcmp(del_mask
, hi
->masks
->list
[i
])) {
2934 char *old_mask
= hi
->masks
->list
[i
];
2935 if (hi
->masks
->used
== 1 && !force
) {
2936 reply("NSMSG_DELMASK_NOTLAST");
2939 hi
->masks
->list
[i
] = hi
->masks
->list
[--hi
->masks
->used
];
2940 reply("NSMSG_DELMASK_SUCCESS", old_mask
);
2945 reply("NSMSG_DELMASK_NOT_FOUND");
2949 static NICKSERV_FUNC(cmd_delmask
)
2951 NICKSERV_MIN_PARMS(2);
2952 return nickserv_delmask(cmd
, user
, user
->handle_info
, argv
[1], 0);
2955 static NICKSERV_FUNC(cmd_odelmask
)
2957 struct handle_info
*hi
;
2958 NICKSERV_MIN_PARMS(3);
2959 if (!(hi
= get_victim_oper(user
, argv
[1])))
2961 return nickserv_delmask(cmd
, user
, hi
, argv
[2], 1);
2965 nickserv_addsslfp(struct userNode
*user
, struct handle_info
*hi
, const char *sslfp
)
2968 char *new_sslfp
= strdup(sslfp
);
2969 for (i
=0; i
<hi
->sslfps
->used
; i
++) {
2970 if (!irccasecmp(new_sslfp
, hi
->sslfps
->list
[i
])) {
2971 send_message(user
, nickserv
, "NSMSG_ADDSSLFP_ALREADY", new_sslfp
);
2976 string_list_append(hi
->sslfps
, new_sslfp
);
2977 send_message(user
, nickserv
, "NSMSG_ADDSSLFP_SUCCESS", new_sslfp
);
2981 static NICKSERV_FUNC(cmd_addsslfp
)
2983 NICKSERV_MIN_PARMS((user
->sslfp
? 1 : 2));
2984 if ((argc
< 2) && (user
->sslfp
)) {
2985 int res
= nickserv_addsslfp(user
, user
->handle_info
, user
->sslfp
);
2988 return nickserv_addsslfp(user
, user
->handle_info
, argv
[1]);
2992 static NICKSERV_FUNC(cmd_oaddsslfp
)
2994 struct handle_info
*hi
;
2996 NICKSERV_MIN_PARMS(3);
2997 if (!(hi
= get_victim_oper(user
, argv
[1])))
2999 return nickserv_addsslfp(user
, hi
, argv
[2]);
3003 nickserv_delsslfp(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, const char *del_sslfp
)
3006 for (i
=0; i
<hi
->sslfps
->used
; i
++) {
3007 if (!irccasecmp(del_sslfp
, hi
->sslfps
->list
[i
])) {
3008 char *old_sslfp
= hi
->sslfps
->list
[i
];
3009 hi
->sslfps
->list
[i
] = hi
->sslfps
->list
[--hi
->sslfps
->used
];
3010 reply("NSMSG_DELSSLFP_SUCCESS", old_sslfp
);
3015 reply("NSMSG_DELSSLFP_NOT_FOUND");
3019 static NICKSERV_FUNC(cmd_delsslfp
)
3021 NICKSERV_MIN_PARMS((user
->sslfp
? 1 : 2));
3022 if ((argc
< 2) && (user
->sslfp
)) {
3023 return nickserv_delsslfp(cmd
, user
, user
->handle_info
, user
->sslfp
);
3025 return nickserv_delsslfp(cmd
, user
, user
->handle_info
, argv
[1]);
3029 static NICKSERV_FUNC(cmd_odelsslfp
)
3031 struct handle_info
*hi
;
3032 NICKSERV_MIN_PARMS(3);
3033 if (!(hi
= get_victim_oper(user
, argv
[1])))
3035 return nickserv_delsslfp(cmd
, user
, hi
, argv
[2]);
3039 nickserv_modify_handle_flags(struct userNode
*user
, struct userNode
*bot
, const char *str
, unsigned long *padded
, unsigned long *premoved
) {
3040 unsigned int nn
, add
= 1, pos
;
3041 unsigned long added
, removed
, flag
;
3043 for (added
=removed
=nn
=0; str
[nn
]; nn
++) {
3045 case '+': add
= 1; break;
3046 case '-': add
= 0; break;
3048 if (!(pos
= handle_inverse_flags
[(unsigned char)str
[nn
]])) {
3049 send_message(user
, bot
, "NSMSG_INVALID_FLAG", str
[nn
]);
3052 if (user
&& (user
->handle_info
->opserv_level
< flag_access_levels
[pos
-1])) {
3053 /* cheesy avoidance of looking up the flag name.. */
3054 send_message(user
, bot
, "NSMSG_FLAG_PRIVILEGED", str
[nn
]);
3057 flag
= 1 << (pos
- 1);
3059 added
|= flag
, removed
&= ~flag
;
3061 removed
|= flag
, added
&= ~flag
;
3066 *premoved
= removed
;
3071 nickserv_apply_flags(struct userNode
*user
, struct handle_info
*hi
, const char *flags
)
3073 unsigned long before
, after
, added
, removed
;
3074 struct userNode
*uNode
;
3076 before
= hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
);
3077 if (!nickserv_modify_handle_flags(user
, nickserv
, flags
, &added
, &removed
))
3079 hi
->flags
= (hi
->flags
| added
) & ~removed
;
3080 after
= hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
);
3082 /* Strip helping flag if they're only a support helper and not
3083 * currently in #support. */
3084 if (HANDLE_FLAGGED(hi
, HELPING
) && (after
== HI_FLAG_SUPPORT_HELPER
)) {
3085 struct channelList
*schannels
;
3087 schannels
= chanserv_support_channels();
3088 for (ii
= 0; ii
< schannels
->used
; ++ii
)
3089 if (find_handle_in_channel(schannels
->list
[ii
], hi
, NULL
))
3091 if (ii
== schannels
->used
)
3092 HANDLE_CLEAR_FLAG(hi
, HELPING
);
3095 if (after
&& !before
) {
3096 /* Add user to current helper list. */
3097 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
3098 userList_append(&curr_helpers
, uNode
);
3099 } else if (!after
&& before
) {
3100 /* Remove user from current helper list. */
3101 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
3102 userList_remove(&curr_helpers
, uNode
);
3109 set_list(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, int override
)
3113 char *set_display
[] = {
3114 "INFO", "WIDTH", "TABLEWIDTH", "COLOR", "PRIVMSG", "STYLE",
3115 "EMAIL", "ANNOUNCEMENTS", "AUTOHIDE", "MAXLOGINS", "LANGUAGE",
3116 "FAKEHOST", "TITLE", "EPITHET", "ADVANCED"
3119 reply("NSMSG_SETTING_LIST");
3120 reply("NSMSG_SETTING_LIST_HEADER");
3122 /* Do this so options are presented in a consistent order. */
3123 for (i
= 0; i
< ArrayLength(set_display
); ++i
)
3124 if ((opt
= dict_find(nickserv_opt_dict
, set_display
[i
], NULL
)))
3125 opt(cmd
, user
, hi
, override
, 0, 0, NULL
);
3126 reply("NSMSG_SETTING_LIST_END");
3129 static NICKSERV_FUNC(cmd_set
)
3131 struct handle_info
*hi
;
3134 hi
= user
->handle_info
;
3136 set_list(cmd
, user
, hi
, 0);
3139 if (!(opt
= dict_find(nickserv_opt_dict
, argv
[1], NULL
))) {
3140 reply("NSMSG_INVALID_OPTION", argv
[1]);
3143 return opt(cmd
, user
, hi
, 0, 0, argc
-1, argv
+1);
3146 static NICKSERV_FUNC(cmd_oset
)
3148 struct handle_info
*hi
;
3151 NICKSERV_MIN_PARMS(2);
3153 if (!(hi
= get_victim_oper(user
, argv
[1])))
3157 set_list(cmd
, user
, hi
, 0);
3161 if (!(opt
= dict_find(nickserv_opt_dict
, argv
[2], NULL
))) {
3162 reply("NSMSG_INVALID_OPTION", argv
[2]);
3166 return opt(cmd
, user
, hi
, 1, 0, argc
-2, argv
+2);
3169 static OPTION_FUNC(opt_info
)
3173 if ((argv
[1][0] == '*') && (argv
[1][1] == 0)) {
3175 hi
->infoline
= NULL
;
3177 hi
->infoline
= strdup(unsplit_string(argv
+1, argc
-1, NULL
));
3181 info
= hi
->infoline
? hi
->infoline
: user_find_message(user
, "MSG_NONE");
3183 reply("NSMSG_SET_INFO", info
);
3187 static OPTION_FUNC(opt_width
)
3190 hi
->screen_width
= strtoul(argv
[1], NULL
, 0);
3192 if ((hi
->screen_width
> 0) && (hi
->screen_width
< MIN_LINE_SIZE
))
3193 hi
->screen_width
= MIN_LINE_SIZE
;
3194 else if (hi
->screen_width
> MAX_LINE_SIZE
)
3195 hi
->screen_width
= MAX_LINE_SIZE
;
3198 reply("NSMSG_SET_WIDTH", hi
->screen_width
);
3202 static OPTION_FUNC(opt_tablewidth
)
3205 hi
->table_width
= strtoul(argv
[1], NULL
, 0);
3207 if ((hi
->table_width
> 0) && (hi
->table_width
< MIN_LINE_SIZE
))
3208 hi
->table_width
= MIN_LINE_SIZE
;
3209 else if (hi
->screen_width
> MAX_LINE_SIZE
)
3210 hi
->table_width
= MAX_LINE_SIZE
;
3213 reply("NSMSG_SET_TABLEWIDTH", hi
->table_width
);
3217 static OPTION_FUNC(opt_color
)
3220 if (enabled_string(argv
[1]))
3221 HANDLE_SET_FLAG(hi
, MIRC_COLOR
);
3222 else if (disabled_string(argv
[1]))
3223 HANDLE_CLEAR_FLAG(hi
, MIRC_COLOR
);
3226 reply("MSG_INVALID_BINARY", argv
[1]);
3232 reply("NSMSG_SET_COLOR", user_find_message(user
, HANDLE_FLAGGED(hi
, MIRC_COLOR
) ? "MSG_ON" : "MSG_OFF"));
3236 static OPTION_FUNC(opt_privmsg
)
3239 if (enabled_string(argv
[1]))
3240 HANDLE_SET_FLAG(hi
, USE_PRIVMSG
);
3241 else if (disabled_string(argv
[1]))
3242 HANDLE_CLEAR_FLAG(hi
, USE_PRIVMSG
);
3245 reply("MSG_INVALID_BINARY", argv
[1]);
3251 reply("NSMSG_SET_PRIVMSG", user_find_message(user
, HANDLE_FLAGGED(hi
, USE_PRIVMSG
) ? "MSG_ON" : "MSG_OFF"));
3255 static OPTION_FUNC(opt_autohide
)
3258 if (enabled_string(argv
[1]))
3259 HANDLE_SET_FLAG(hi
, AUTOHIDE
);
3260 else if (disabled_string(argv
[1]))
3261 HANDLE_CLEAR_FLAG(hi
, AUTOHIDE
);
3264 reply("MSG_INVALID_BINARY", argv
[1]);
3270 reply("NSMSG_SET_AUTOHIDE", user_find_message(user
, HANDLE_FLAGGED(hi
, AUTOHIDE
) ? "MSG_ON" : "MSG_OFF"));
3274 static OPTION_FUNC(opt_style
)
3279 if (!irccasecmp(argv
[1], "Clean"))
3280 hi
->userlist_style
= HI_STYLE_CLEAN
;
3281 else if (!irccasecmp(argv
[1], "Advanced"))
3282 hi
->userlist_style
= HI_STYLE_ADVANCED
;
3283 else if (!irccasecmp(argv
[1], "Classic"))
3284 hi
->userlist_style
= HI_STYLE_CLASSIC
;
3285 else /* Default to normal */
3286 hi
->userlist_style
= HI_STYLE_NORMAL
;
3287 } /* TODO: give error if unknow style is chosen */
3289 switch (hi
->userlist_style
) {
3290 case HI_STYLE_ADVANCED
:
3293 case HI_STYLE_CLASSIC
:
3296 case HI_STYLE_CLEAN
:
3299 case HI_STYLE_NORMAL
:
3305 reply("NSMSG_SET_STYLE", style
);
3309 static OPTION_FUNC(opt_announcements
)
3314 if (enabled_string(argv
[1]))
3315 hi
->announcements
= 'y';
3316 else if (disabled_string(argv
[1]))
3317 hi
->announcements
= 'n';
3318 else if (!strcmp(argv
[1], "?") || !irccasecmp(argv
[1], "default"))
3319 hi
->announcements
= '?';
3322 reply("NSMSG_INVALID_ANNOUNCE", argv
[1]);
3327 switch (hi
->announcements
) {
3328 case 'y': choice
= user_find_message(user
, "MSG_ON"); break;
3329 case 'n': choice
= user_find_message(user
, "MSG_OFF"); break;
3330 case '?': choice
= "default"; break;
3331 default: choice
= "unknown"; break;
3334 reply("NSMSG_SET_ANNOUNCEMENTS", choice
);
3338 static OPTION_FUNC(opt_password
)
3340 char crypted
[MD5_CRYPT_LENGTH
+1];
3346 reply("NSMSG_USE_CMD_PASS");
3350 cryptpass(argv
[1], crypted
);
3352 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
3354 if((rc
= ldap_do_modify(hi
->handle
, crypted
, NULL
)) != LDAP_SUCCESS
) {
3356 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3361 strcpy(hi
->passwd
, crypted
);
3362 if (nickserv_conf
.sync_log
)
3363 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
3366 reply("NSMSG_SET_PASSWORD", "***");
3370 static OPTION_FUNC(opt_flags
)
3373 unsigned int ii
, flen
;
3377 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3382 nickserv_apply_flags(user
, hi
, argv
[1]);
3384 for (ii
= flen
= 0; handle_flags
[ii
]; ii
++)
3385 if (hi
->flags
& (1 << ii
))
3386 flags
[flen
++] = handle_flags
[ii
];
3390 reply("NSMSG_SET_FLAGS", flags
);
3392 reply("NSMSG_SET_FLAGS", user_find_message(user
, "MSG_NONE"));
3397 static OPTION_FUNC(opt_email
)
3401 if (!valid_email(argv
[1])) {
3403 reply("NSMSG_BAD_EMAIL_ADDR");
3406 if ((str
= mail_prohibited_address(argv
[1]))) {
3408 reply("NSMSG_EMAIL_PROHIBITED", argv
[1], str
);
3411 if (hi
->email_addr
&& !irccasecmp(hi
->email_addr
, argv
[1])) {
3413 reply("NSMSG_EMAIL_SAME");
3414 } else if (!override
)
3415 nickserv_make_cookie(user
, hi
, EMAIL_CHANGE
, argv
[1], 0);
3418 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
3420 if((rc
= ldap_do_modify(hi
->handle
, NULL
, argv
[1])) != LDAP_SUCCESS
) {
3422 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3427 nickserv_set_email_addr(hi
, argv
[1]);
3429 nickserv_eat_cookie(hi
->cookie
);
3431 reply("NSMSG_SET_EMAIL", visible_email_addr(user
, hi
));
3435 reply("NSMSG_SET_EMAIL", visible_email_addr(user
, hi
));
3440 static OPTION_FUNC(opt_maxlogins
)
3442 unsigned char maxlogins
;
3444 maxlogins
= strtoul(argv
[1], NULL
, 0);
3445 if ((maxlogins
> nickserv_conf
.hard_maxlogins
) && !override
) {
3447 reply("NSMSG_BAD_MAX_LOGINS", nickserv_conf
.hard_maxlogins
);
3450 hi
->maxlogins
= maxlogins
;
3452 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
3454 reply("NSMSG_SET_MAXLOGINS", maxlogins
);
3458 static OPTION_FUNC(opt_advanced
)
3461 if (enabled_string(argv
[1]))
3462 HANDLE_SET_FLAG(hi
, ADVANCED
);
3463 else if (disabled_string(argv
[1]))
3464 HANDLE_CLEAR_FLAG(hi
, ADVANCED
);
3467 reply("MSG_INVALID_BINARY", argv
[1]);
3473 reply("NSMSG_SET_ADVANCED", user_find_message(user
, HANDLE_FLAGGED(hi
, ADVANCED
) ? "MSG_ON" : "MSG_OFF"));
3477 static OPTION_FUNC(opt_language
)
3479 struct language
*lang
;
3481 lang
= language_find(argv
[1]);
3482 if (irccasecmp(lang
->name
, argv
[1])) {
3484 reply("NSMSG_LANGUAGE_NOT_FOUND", argv
[1], lang
->name
);
3486 hi
->language
= lang
;
3489 reply("NSMSG_SET_LANGUAGE", hi
->language
->name
);
3493 static OPTION_FUNC(opt_karma
)
3497 send_message(user
, nickserv
, "MSG_SETTING_PRIVILEGED", argv
[0]);
3502 if (argv
[1][0] == '+' && isdigit(argv
[1][1])) {
3503 hi
->karma
+= strtoul(argv
[1] + 1, NULL
, 10);
3504 } else if (argv
[1][0] == '-' && isdigit(argv
[1][1])) {
3505 hi
->karma
-= strtoul(argv
[1] + 1, NULL
, 10);
3508 send_message(user
, nickserv
, "NSMSG_INVALID_KARMA", argv
[1]);
3513 send_message(user
, nickserv
, "NSMSG_SET_KARMA", hi
->karma
);
3517 /* Called from opserv from cmd_access */
3519 oper_try_set_access(struct userNode
*user
, struct userNode
*bot
, struct handle_info
*target
, unsigned int new_level
) {
3520 if (!oper_has_access(user
, bot
, nickserv_conf
.modoper_level
, 0))
3522 if ((user
->handle_info
->opserv_level
< target
->opserv_level
)
3523 || ((user
->handle_info
->opserv_level
== target
->opserv_level
)
3524 && (user
->handle_info
->opserv_level
< 1000))) {
3525 send_message(user
, bot
, "MSG_USER_OUTRANKED", target
->handle
);
3528 if ((user
->handle_info
->opserv_level
< new_level
)
3529 || ((user
->handle_info
->opserv_level
== new_level
)
3530 && (user
->handle_info
->opserv_level
< 1000))) {
3531 send_message(user
, bot
, "NSMSG_OPSERV_LEVEL_BAD");
3534 if (user
->handle_info
== target
) {
3535 send_message(user
, bot
, "MSG_STUPID_ACCESS_CHANGE");
3539 if(nickserv_conf
.ldap_enable
&& *(nickserv_conf
.ldap_oper_group_dn
) && *(nickserv_conf
.ldap_admin_dn
)) {
3541 if(new_level
> nickserv_conf
.ldap_oper_group_level
)
3542 rc
= ldap_add2group(target
->handle
, nickserv_conf
.ldap_oper_group_dn
);
3544 rc
= ldap_delfromgroup(target
->handle
, nickserv_conf
.ldap_oper_group_dn
);
3545 if(rc
!= LDAP_SUCCESS
&& rc
!= LDAP_TYPE_OR_VALUE_EXISTS
&& rc
!= LDAP_NO_SUCH_ATTRIBUTE
) {
3546 send_message(user
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3550 if(nickserv_conf
.ldap_enable
&& *(nickserv_conf
.ldap_field_oslevel
) && *(nickserv_conf
.ldap_admin_dn
)) {
3552 if((rc
= ldap_do_oslevel(target
->handle
, new_level
, target
->opserv_level
)) != LDAP_SUCCESS
) {
3553 send_message(user
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3558 if (target
->opserv_level
== new_level
)
3560 log_module(NS_LOG
, LOG_INFO
, "Account %s setting oper level for account %s to %d (from %d).",
3561 user
->handle_info
->handle
, target
->handle
, new_level
, target
->opserv_level
);
3562 target
->opserv_level
= new_level
;
3566 static OPTION_FUNC(opt_level
)
3572 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3576 res
= (argc
> 1) ? oper_try_set_access(user
, nickserv
, hi
, strtoul(argv
[1], NULL
, 0)) : 0;
3578 reply("NSMSG_SET_LEVEL", hi
->opserv_level
);
3582 static OPTION_FUNC(opt_epithet
)
3584 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_epithet_level
, 0)) {
3586 struct userNode
*target
, *next_un
;
3590 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3594 epithet
= unsplit_string(argv
+1, argc
-1, NULL
);
3598 if ((epithet
[0] == '*') && !epithet
[1])
3601 hi
->epithet
= strdup(epithet
);
3603 for (target
= hi
->users
; target
; target
= next_un
) {
3604 irc_swhois(nickserv
, target
, hi
->epithet
);
3606 next_un
= target
->next_authed
;
3612 reply("NSMSG_SET_EPITHET", hi
->epithet
);
3614 reply("NSMSG_SET_EPITHET", user_find_message(user
, "MSG_NONE"));
3619 static OPTION_FUNC(opt_title
)
3622 const char *none
= NULL
;
3625 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_title_level
, 0)) {
3628 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3633 if(!strcmp(title
, "*")) {
3635 hi
->fakehost
= NULL
;
3638 if (strchr(title
, '.')) {
3640 reply("NSMSG_TITLE_INVALID");
3643 /* Alphanumeric titles only. */
3644 for(sptr
= title
; *sptr
; sptr
++) {
3645 if(!isalnum(*sptr
) && *sptr
!= '-') {
3647 reply("NSMSG_TITLE_INVALID");
3651 if ((strlen(user
->handle_info
->handle
) + strlen(title
) +
3652 strlen(nickserv_conf
.titlehost_suffix
) + 2) > HOSTLEN
) {
3654 reply("NSMSG_TITLE_TRUNCATED");
3658 hi
->fakehost
= malloc(strlen(title
)+2);
3659 hi
->fakehost
[0] = '.';
3660 strcpy(hi
->fakehost
+1, title
);
3663 } else if (hi
->fakehost
&& (hi
->fakehost
[0] == '.'))
3664 title
= hi
->fakehost
+ 1;
3666 /* If theres no title set then the default title will therefore
3667 be the first part of hidden_host in x3.conf, so for
3668 consistency with opt_fakehost we will print this here.
3669 This isnt actually used in P10, its just handled to keep from crashing... */
3670 char *hs
, *hidden_suffix
, *rest
;
3672 hs
= conf_get_data("server/hidden_host", RECDB_QSTRING
);
3673 hidden_suffix
= strdup(hs
);
3675 /* Yes we do this twice */
3676 if((rest
= strchr(hidden_suffix
, '.')))
3679 title
= hidden_suffix
;
3683 /* A lame default if someone configured hidden_host to something lame */
3684 title
= strdup("users");
3685 free(hidden_suffix
);
3691 none
= user_find_message(user
, "MSG_NONE");
3693 send_message(user
, nickserv
, "NSMSG_SET_TITLE", title
? title
: none
);
3698 check_vhost(char *vhost
, struct userNode
*user
, struct svccmd
*cmd
)
3702 // check for a dot in the vhost
3703 if(strchr(vhost
, '.') == NULL
) {
3704 reply("NSMSG_NOT_VALID_FAKEHOST_DOT", vhost
);
3708 // check for a @ in the vhost
3709 if(strchr(vhost
, '@') != NULL
) {
3710 reply("NSMSG_NOT_VALID_FAKEHOST_AT", vhost
);
3714 // check for denied words, inspired by monk at paki.sex
3715 for(y
= 0; y
< nickserv_conf
.denied_fakehost_words
->used
; y
++) {
3716 if(strstr(vhost
, nickserv_conf
.denied_fakehost_words
->list
[y
]) != NULL
) {
3717 reply("NSMSG_DENIED_FAKEHOST_WORD", vhost
, nickserv_conf
.denied_fakehost_words
->list
[y
]);
3722 // check for ircu's HOSTLEN length.
3723 if(strlen(vhost
) >= HOSTLEN
) {
3724 reply("NSMSG_NOT_VALID_FAKEHOST_LEN", vhost
);
3728 /* This can be handled by the regex now if desired.
3729 if (vhost[strspn(vhost, "0123456789.")]) {
3730 hostname = vhost + strlen(vhost);
3731 for (depth = 1; depth && (hostname > vhost); depth--) {
3733 while ((hostname > vhost) && (*hostname != '.')) hostname--;
3736 if (*hostname == '.') hostname++; * advance past last dot we saw *
3737 if(strlen(hostname) > 4) {
3738 reply("NSMSG_NOT_VALID_FAKEHOST_TLD_LEN", vhost);
3743 /* test either regex or as valid handle */
3744 if (nickserv_conf
.valid_fakehost_regex_set
) {
3745 int err
= regexec(&nickserv_conf
.valid_fakehost_regex
, vhost
, 0, 0, 0);
3748 buff
[regerror(err
, &nickserv_conf
.valid_fakehost_regex
, buff
, sizeof(buff
))] = 0;
3749 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
3751 if(err
== REG_NOMATCH
) {
3752 reply("NSMSG_NOT_VALID_FAKEHOST_REGEX", vhost
);
3761 static OPTION_FUNC(opt_fakehost
)
3765 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_fakehost_level
, 0)) {
3768 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3773 if ((strlen(fake
) > HOSTLEN
) || (fake
[0] == '.')) {
3775 reply("NSMSG_FAKEHOST_INVALID", HOSTLEN
);
3778 if (!strcmp(fake
, "*")) {
3781 hi
->fakehost
= NULL
;
3784 else if (!check_vhost(argv
[1], user
, cmd
)) {
3785 /* check_vhost takes care of error reply */
3791 hi
->fakehost
= strdup(fake
);
3794 fake
= hi
->fakehost
;
3796 fake
= generate_fakehost(hi
);
3798 /* Tell them we set the host */
3800 fake
= user_find_message(user
, "MSG_NONE");
3802 reply("NSMSG_SET_FAKEHOST", fake
);
3806 static OPTION_FUNC(opt_note
)
3810 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3815 char *text
= unsplit_string(argv
+ 1, argc
- 1, NULL
);
3820 if ((text
[0] == '*') && !text
[1])
3823 if (!(hi
->note
= nickserv_add_note(user
->handle_info
->handle
, now
, text
)))
3829 reply("NSMSG_SET_NOTE", hi
->note
? hi
->note
->note
: user_find_message(user
, "MSG_NONE"));
3833 static NICKSERV_FUNC(cmd_reclaim
)
3835 struct handle_info
*hi
;
3836 struct nick_info
*ni
;
3837 struct userNode
*victim
;
3839 NICKSERV_MIN_PARMS(2);
3840 hi
= user
->handle_info
;
3841 ni
= dict_find(nickserv_nick_dict
, argv
[1], 0);
3843 reply("NSMSG_UNKNOWN_NICK", argv
[1]);
3846 if (ni
->owner
!= user
->handle_info
) {
3847 reply("NSMSG_NOT_YOUR_NICK", ni
->nick
);
3850 victim
= GetUserH(ni
->nick
);
3852 reply("MSG_NICK_UNKNOWN", ni
->nick
);
3855 if (victim
== user
) {
3856 reply("NSMSG_NICK_USER_YOU");
3859 nickserv_reclaim(victim
, ni
, nickserv_conf
.reclaim_action
);
3860 switch (nickserv_conf
.reclaim_action
) {
3861 case RECLAIM_NONE
: reply("NSMSG_RECLAIMED_NONE"); break;
3862 case RECLAIM_WARN
: reply("NSMSG_RECLAIMED_WARN", victim
->nick
); break;
3863 case RECLAIM_SVSNICK
: reply("NSMSG_RECLAIMED_SVSNICK", victim
->nick
); break;
3864 case RECLAIM_KILL
: reply("NSMSG_RECLAIMED_KILL", victim
->nick
); break;
3869 static NICKSERV_FUNC(cmd_unregnick
)
3872 struct handle_info
*hi
;
3873 struct nick_info
*ni
;
3875 hi
= user
->handle_info
;
3876 nick
= (argc
< 2) ? user
->nick
: (const char*)argv
[1];
3877 ni
= dict_find(nickserv_nick_dict
, nick
, NULL
);
3879 reply("NSMSG_UNKNOWN_NICK", nick
);
3882 if (hi
!= ni
->owner
) {
3883 reply("NSMSG_NOT_YOUR_NICK", nick
);
3886 reply("NSMSG_UNREGNICK_SUCCESS", ni
->nick
);
3891 static NICKSERV_FUNC(cmd_ounregnick
)
3893 struct nick_info
*ni
;
3895 NICKSERV_MIN_PARMS(2);
3896 if (!(ni
= get_nick_info(argv
[1]))) {
3897 reply("NSMSG_NICK_NOT_REGISTERED", argv
[1]);
3900 if (!oper_outranks(user
, ni
->owner
))
3902 reply("NSMSG_UNREGNICK_SUCCESS", ni
->nick
);
3907 static NICKSERV_FUNC(cmd_unregister
)
3909 struct handle_info
*hi
;
3912 NICKSERV_MIN_PARMS(2);
3913 hi
= user
->handle_info
;
3916 if (checkpass(passwd
, hi
->passwd
)) {
3917 if(nickserv_unregister_handle(hi
, user
, cmd
->parent
->bot
))
3922 log_module(NS_LOG
, LOG_INFO
, "Account '%s' tried to unregister with the wrong password.", hi
->handle
);
3923 reply("NSMSG_PASSWORD_INVALID");
3928 static NICKSERV_FUNC(cmd_ounregister
)
3930 struct handle_info
*hi
;
3931 char reason
[MAXLEN
];
3934 NICKSERV_MIN_PARMS(2);
3935 if (!(hi
= get_victim_oper(user
, argv
[1])))
3938 if (HANDLE_FLAGGED(hi
, NODELETE
)) {
3939 reply("NSMSG_UNREGISTER_NODELETE", hi
->handle
);
3943 force
= IsOper(user
) && (argc
> 2) && !irccasecmp(argv
[2], "force");
3945 ((hi
->flags
& nickserv_conf
.ounregister_flags
)
3947 || (hi
->last_quit_host
[0] && ((unsigned)(now
- hi
->lastseen
) < nickserv_conf
.ounregister_inactive
)))) {
3948 reply((IsOper(user
) ? "NSMSG_UNREGISTER_MUST_FORCE" : "NSMSG_UNREGISTER_CANNOT_FORCE"), hi
->handle
);
3951 snprintf(reason
, sizeof(reason
), "%s unregistered account %s.", user
->handle_info
->handle
, hi
->handle
);
3952 global_message(MESSAGE_RECIPIENT_STAFF
, reason
);
3953 if(nickserv_unregister_handle(hi
, user
, cmd
->parent
->bot
))
3959 static NICKSERV_FUNC(cmd_status
)
3961 if (nickserv_conf
.disable_nicks
) {
3962 reply("NSMSG_GLOBAL_STATS_NONICK",
3963 dict_size(nickserv_handle_dict
));
3965 if (user
->handle_info
) {
3967 struct nick_info
*ni
;
3968 for (ni
=user
->handle_info
->nicks
; ni
; ni
=ni
->next
) cnt
++;
3969 reply("NSMSG_HANDLE_STATS", cnt
);
3971 reply("NSMSG_HANDLE_NONE");
3973 reply("NSMSG_GLOBAL_STATS",
3974 dict_size(nickserv_handle_dict
),
3975 dict_size(nickserv_nick_dict
));
3980 static NICKSERV_FUNC(cmd_ghost
)
3982 struct userNode
*target
;
3983 char reason
[MAXLEN
];
3985 NICKSERV_MIN_PARMS(2);
3986 if (!(target
= GetUserH(argv
[1]))) {
3987 reply("MSG_NICK_UNKNOWN", argv
[1]);
3990 if (target
== user
) {
3991 reply("NSMSG_CANNOT_GHOST_SELF");
3994 if (!target
->handle_info
|| (target
->handle_info
!= user
->handle_info
)) {
3995 reply("NSMSG_CANNOT_GHOST_USER", target
->nick
);
3998 snprintf(reason
, sizeof(reason
), "Ghost kill on account %s (requested by %s).", target
->handle_info
->handle
, user
->nick
);
3999 DelUser(target
, nickserv
, 1, reason
);
4000 reply("NSMSG_GHOST_KILLED", argv
[1]);
4004 static NICKSERV_FUNC(cmd_vacation
)
4006 HANDLE_SET_FLAG(user
->handle_info
, FROZEN
);
4007 reply("NSMSG_ON_VACATION");
4012 nickserv_saxdb_write(struct saxdb_context
*ctx
) {
4014 struct handle_info
*hi
;
4017 for (it
= dict_first(nickserv_handle_dict
); it
; it
= iter_next(it
)) {
4019 saxdb_start_record(ctx
, iter_key(it
), 0);
4020 if (hi
->announcements
!= '?') {
4021 flags
[0] = hi
->announcements
;
4023 saxdb_write_string(ctx
, KEY_ANNOUNCEMENTS
, flags
);
4026 struct handle_cookie
*cookie
= hi
->cookie
;
4029 switch (cookie
->type
) {
4030 case ACTIVATION
: type
= KEY_ACTIVATION
; break;
4031 case PASSWORD_CHANGE
: type
= KEY_PASSWORD_CHANGE
; break;
4032 case EMAIL_CHANGE
: type
= KEY_EMAIL_CHANGE
; break;
4033 case ALLOWAUTH
: type
= KEY_ALLOWAUTH
; break;
4034 default: type
= NULL
; break;
4037 saxdb_start_record(ctx
, KEY_COOKIE
, 0);
4038 saxdb_write_string(ctx
, KEY_COOKIE_TYPE
, type
);
4039 saxdb_write_int(ctx
, KEY_COOKIE_EXPIRES
, cookie
->expires
);
4041 saxdb_write_string(ctx
, KEY_COOKIE_DATA
, cookie
->data
);
4042 saxdb_write_string(ctx
, KEY_COOKIE
, cookie
->cookie
);
4043 saxdb_end_record(ctx
);
4047 saxdb_write_string(ctx
, KEY_EMAIL_ADDR
, hi
->email_addr
);
4049 saxdb_write_string(ctx
, KEY_EPITHET
, hi
->epithet
);
4051 saxdb_start_record(ctx
, KEY_NOTE_NOTE
, 0);
4052 saxdb_write_string(ctx
, KEY_NOTE_SETTER
, hi
->note
->setter
);
4053 saxdb_write_int(ctx
, KEY_NOTE_DATE
, hi
->note
->date
);
4054 saxdb_write_string(ctx
, KEY_NOTE_NOTE
, hi
->note
->note
);
4055 saxdb_end_record(ctx
);
4059 saxdb_write_string(ctx
, KEY_FAKEHOST
, hi
->fakehost
);
4063 for (ii
=flen
=0; handle_flags
[ii
]; ++ii
)
4064 if (hi
->flags
& (1 << ii
))
4065 flags
[flen
++] = handle_flags
[ii
];
4067 saxdb_write_string(ctx
, KEY_FLAGS
, flags
);
4070 saxdb_write_string(ctx
, KEY_INFO
, hi
->infoline
);
4071 if (hi
->last_quit_host
[0])
4072 saxdb_write_string(ctx
, KEY_LAST_QUIT_HOST
, hi
->last_quit_host
);
4073 saxdb_write_int(ctx
, KEY_LAST_SEEN
, hi
->lastseen
);
4075 saxdb_write_sint(ctx
, KEY_KARMA
, hi
->karma
);
4076 if (hi
->masks
->used
)
4077 saxdb_write_string_list(ctx
, KEY_MASKS
, hi
->masks
);
4078 if (hi
->sslfps
->used
)
4079 saxdb_write_string_list(ctx
, KEY_SSLFPS
, hi
->sslfps
);
4080 if (hi
->ignores
->used
)
4081 saxdb_write_string_list(ctx
, KEY_IGNORES
, hi
->ignores
);
4083 saxdb_write_int(ctx
, KEY_MAXLOGINS
, hi
->maxlogins
);
4085 struct string_list
*slist
;
4086 struct nick_info
*ni
;
4088 slist
= alloc_string_list(nickserv_conf
.nicks_per_handle
);
4089 for (ni
= hi
->nicks
; ni
; ni
= ni
->next
) string_list_append(slist
, ni
->nick
);
4090 saxdb_write_string_list(ctx
, KEY_NICKS
, slist
);
4094 saxdb_start_record(ctx
, KEY_NICKS_EX
, 0);
4095 for (ni
= hi
->nicks
; ni
; ni
= ni
->next
) {
4096 saxdb_start_record(ctx
, ni
->nick
, 0);
4097 saxdb_write_int(ctx
, KEY_REGISTER_ON
, ni
->registered
);
4098 saxdb_write_int(ctx
, KEY_LAST_SEEN
, ni
->lastseen
);
4099 saxdb_end_record(ctx
);
4101 saxdb_end_record(ctx
);
4103 if (hi
->opserv_level
)
4104 saxdb_write_int(ctx
, KEY_OPSERV_LEVEL
, hi
->opserv_level
);
4105 if (hi
->language
!= lang_C
)
4106 saxdb_write_string(ctx
, KEY_LANGUAGE
, hi
->language
->name
);
4107 saxdb_write_string(ctx
, KEY_PASSWD
, hi
->passwd
);
4108 saxdb_write_int(ctx
, KEY_REGISTER_ON
, hi
->registered
);
4109 if (hi
->screen_width
)
4110 saxdb_write_int(ctx
, KEY_SCREEN_WIDTH
, hi
->screen_width
);
4111 if (hi
->table_width
)
4112 saxdb_write_int(ctx
, KEY_TABLE_WIDTH
, hi
->table_width
);
4113 flags
[0] = hi
->userlist_style
;
4115 saxdb_write_string(ctx
, KEY_USERLIST_STYLE
, flags
);
4116 saxdb_end_record(ctx
);
4122 static handle_merge_func_t
*handle_merge_func_list
;
4123 static void **handle_merge_func_list_extra
;
4124 static unsigned int handle_merge_func_size
= 0, handle_merge_func_used
= 0;
4127 reg_handle_merge_func(handle_merge_func_t func
, void *extra
)
4129 if (handle_merge_func_used
== handle_merge_func_size
) {
4130 if (handle_merge_func_size
) {
4131 handle_merge_func_size
<<= 1;
4132 handle_merge_func_list
= realloc(handle_merge_func_list
, handle_merge_func_size
*sizeof(handle_merge_func_t
));
4133 handle_merge_func_list_extra
= realloc(handle_merge_func_list_extra
, handle_merge_func_size
*sizeof(void*));
4135 handle_merge_func_size
= 8;
4136 handle_merge_func_list
= malloc(handle_merge_func_size
*sizeof(handle_merge_func_t
));
4137 handle_merge_func_list_extra
= malloc(handle_merge_func_size
*sizeof(void*));
4140 handle_merge_func_list
[handle_merge_func_used
] = func
;
4141 handle_merge_func_list_extra
[handle_merge_func_used
++] = extra
;
4144 static NICKSERV_FUNC(cmd_merge
)
4146 struct handle_info
*hi_from
, *hi_to
;
4147 struct userNode
*last_user
;
4148 struct userData
*cList
, *cListNext
;
4149 unsigned int ii
, jj
, n
;
4151 NICKSERV_MIN_PARMS(3);
4153 if (!(hi_from
= get_victim_oper(user
, argv
[1])))
4155 if (!(hi_to
= get_victim_oper(user
, argv
[2])))
4157 if (hi_to
== hi_from
) {
4158 reply("NSMSG_CANNOT_MERGE_SELF", hi_to
->handle
);
4162 for (n
=0; n
<handle_merge_func_used
; n
++)
4163 handle_merge_func_list
[n
](user
, hi_to
, hi_from
, handle_merge_func_list_extra
[n
]);
4165 /* Append "from" handle's nicks to "to" handle's nick list. */
4167 struct nick_info
*last_ni
;
4168 for (last_ni
=hi_to
->nicks
; last_ni
->next
; last_ni
=last_ni
->next
) ;
4169 last_ni
->next
= hi_from
->nicks
;
4171 while (hi_from
->nicks
) {
4172 hi_from
->nicks
->owner
= hi_to
;
4173 hi_from
->nicks
= hi_from
->nicks
->next
;
4176 /* Merge the hostmasks. */
4177 for (ii
=0; ii
<hi_from
->masks
->used
; ii
++) {
4178 char *mask
= hi_from
->masks
->list
[ii
];
4179 for (jj
=0; jj
<hi_to
->masks
->used
; jj
++)
4180 if (match_ircglobs(hi_to
->masks
->list
[jj
], mask
))
4182 if (jj
==hi_to
->masks
->used
) /* Nothing from the "to" handle covered this mask, so add it. */
4183 string_list_append(hi_to
->masks
, strdup(mask
));
4186 /* Merge the SSL fingerprints. */
4187 for (ii
=0; ii
<hi_from
->sslfps
->used
; ii
++) {
4188 char *sslfp
= hi_from
->sslfps
->list
[ii
];
4189 for (jj
=0; jj
<hi_to
->sslfps
->used
; jj
++)
4190 if (!irccasecmp(hi_to
->sslfps
->list
[jj
], sslfp
))
4192 if (jj
==hi_to
->sslfps
->used
) /* Nothing from the "to" handle covered this sslfp, so add it. */
4193 string_list_append(hi_to
->sslfps
, strdup(sslfp
));
4196 /* Merge the ignores. */
4197 for (ii
=0; ii
<hi_from
->ignores
->used
; ii
++) {
4198 char *ignore
= hi_from
->ignores
->list
[ii
];
4199 for (jj
=0; jj
<hi_to
->ignores
->used
; jj
++)
4200 if (match_ircglobs(hi_to
->ignores
->list
[jj
], ignore
))
4202 if (jj
==hi_to
->ignores
->used
) /* Nothing from the "to" handle covered this mask, so add it. */
4203 string_list_append(hi_to
->ignores
, strdup(ignore
));
4206 /* Merge the lists of authed users. */
4208 for (last_user
=hi_to
->users
; last_user
->next_authed
; last_user
=last_user
->next_authed
) ;
4209 last_user
->next_authed
= hi_from
->users
;
4211 hi_to
->users
= hi_from
->users
;
4213 /* Repoint the old "from" handle's users. */
4214 for (last_user
=hi_from
->users
; last_user
; last_user
=last_user
->next_authed
) {
4215 last_user
->handle_info
= hi_to
;
4217 hi_from
->users
= NULL
;
4219 /* Merge channel userlists. */
4220 for (cList
=hi_from
->channels
; cList
; cList
=cListNext
) {
4221 struct userData
*cList2
;
4222 cListNext
= cList
->u_next
;
4223 for (cList2
=hi_to
->channels
; cList2
; cList2
=cList2
->u_next
)
4224 if (cList
->channel
== cList2
->channel
)
4226 if (cList2
&& (cList2
->access
>= cList
->access
)) {
4227 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
);
4228 /* keep cList2 in hi_to; remove cList from hi_from */
4229 del_channel_user(cList
, 1);
4232 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
);
4233 /* remove the lower-ranking cList2 from hi_to */
4234 del_channel_user(cList2
, 1);
4236 log_module(NS_LOG
, LOG_INFO
, "Merge: %s had no access in %s", hi_to
->handle
, cList
->channel
->channel
->name
);
4238 /* cList needs to be moved from hi_from to hi_to */
4239 cList
->handle
= hi_to
;
4240 /* Remove from linked list for hi_from */
4241 assert(!cList
->u_prev
);
4242 hi_from
->channels
= cList
->u_next
;
4244 cList
->u_next
->u_prev
= cList
->u_prev
;
4245 /* Add to linked list for hi_to */
4246 cList
->u_prev
= NULL
;
4247 cList
->u_next
= hi_to
->channels
;
4248 if (hi_to
->channels
)
4249 hi_to
->channels
->u_prev
= cList
;
4250 hi_to
->channels
= cList
;
4254 /* Do they get an OpServ level promotion? */
4255 if (hi_from
->opserv_level
> hi_to
->opserv_level
)
4256 hi_to
->opserv_level
= hi_from
->opserv_level
;
4258 /* What about last seen time? */
4259 if (hi_from
->lastseen
> hi_to
->lastseen
)
4260 hi_to
->lastseen
= hi_from
->lastseen
;
4262 /* New karma is the sum of the two original karmas. */
4263 hi_to
->karma
+= hi_from
->karma
;
4265 /* Does a fakehost carry over? (This intentionally doesn't set it
4266 * for users previously attached to hi_to. They'll just have to
4269 if (hi_from
->fakehost
&& !hi_to
->fakehost
)
4270 hi_to
->fakehost
= strdup(hi_from
->fakehost
);
4272 /* Notify of success. */
4273 reply("NSMSG_HANDLES_MERGED", hi_from
->handle
, hi_to
->handle
);
4274 global_message_args(MESSAGE_RECIPIENT_OPERS
, "NSMSG_ACCOUNT_MERGED", user
->nick
,
4275 user
->handle_info
->handle
, hi_from
->handle
, hi_to
->handle
);
4277 /* Unregister the "from" handle. */
4278 nickserv_unregister_handle(hi_from
, NULL
, cmd
->parent
->bot
);
4279 /* TODO: fix it so that if the ldap delete in nickserv_unregister_handle fails,
4280 * the process isn't completed.
4286 struct nickserv_discrim
{
4287 unsigned long flags_on
, flags_off
;
4288 time_t min_registered
, max_registered
;
4291 int min_level
, max_level
;
4292 int min_karma
, max_karma
;
4293 enum { SUBSET
, EXACT
, SUPERSET
, LASTQUIT
} hostmask_type
;
4294 const char *nickmask
;
4295 const char *hostmask
;
4296 const char *handlemask
;
4297 const char *emailmask
;
4298 const char *titlemask
;
4299 const char *setwhat
;
4303 unsigned int inldap
;
4307 typedef void (*discrim_search_func
)(struct userNode
*source
, struct handle_info
*hi
, struct nickserv_discrim
*discrim
);
4309 struct discrim_apply_info
{
4310 struct nickserv_discrim
*discrim
;
4311 discrim_search_func func
;
4312 struct userNode
*source
;
4313 unsigned int matched
;
4316 static struct nickserv_discrim
*
4317 nickserv_discrim_create(struct svccmd
*cmd
, struct userNode
*user
, unsigned int argc
, char *argv
[])
4320 struct nickserv_discrim
*discrim
;
4322 discrim
= malloc(sizeof(*discrim
));
4323 memset(discrim
, 0, sizeof(*discrim
));
4324 discrim
->min_level
= 0;
4325 discrim
->max_level
= INT_MAX
;
4326 discrim
->limit
= 50;
4327 discrim
->min_registered
= 0;
4328 discrim
->max_registered
= INT_MAX
;
4329 discrim
->lastseen
= LONG_MAX
;
4330 discrim
->min_karma
= INT_MIN
;
4331 discrim
->max_karma
= INT_MAX
;
4334 discrim
->inldap
= 2;
4337 for (i
=0; i
<argc
; i
++) {
4338 if (i
== argc
- 1) {
4339 reply("MSG_MISSING_PARAMS", argv
[i
]);
4342 if (!irccasecmp(argv
[i
], "limit")) {
4343 discrim
->limit
= strtoul(argv
[++i
], NULL
, 0);
4344 } else if (!irccasecmp(argv
[i
], "flags")) {
4345 nickserv_modify_handle_flags(user
, nickserv
, argv
[++i
], &discrim
->flags_on
, &discrim
->flags_off
);
4346 } else if (!irccasecmp(argv
[i
], "registered")) {
4347 const char *cmp
= argv
[++i
];
4348 if (cmp
[0] == '<') {
4349 if (cmp
[1] == '=') {
4350 discrim
->min_registered
= now
- ParseInterval(cmp
+2);
4352 discrim
->min_registered
= now
- ParseInterval(cmp
+1) + 1;
4354 } else if (cmp
[0] == '=') {
4355 discrim
->min_registered
= discrim
->max_registered
= now
- ParseInterval(cmp
+1);
4356 } else if (cmp
[0] == '>') {
4357 if (cmp
[1] == '=') {
4358 discrim
->max_registered
= now
- ParseInterval(cmp
+2);
4360 discrim
->max_registered
= now
- ParseInterval(cmp
+1) - 1;
4363 reply("MSG_INVALID_CRITERIA", cmp
);
4365 } else if (!irccasecmp(argv
[i
], "seen")) {
4366 discrim
->lastseen
= now
- ParseInterval(argv
[++i
]);
4367 } else if (!nickserv_conf
.disable_nicks
&& !irccasecmp(argv
[i
], "nickmask")) {
4368 discrim
->nickmask
= argv
[++i
];
4369 } else if (!irccasecmp(argv
[i
], "setwhat")) {
4370 discrim
->setwhat
= argv
[++i
];
4371 if (!(dict_find(nickserv_opt_dict
, discrim
->setwhat
, NULL
))) {
4372 reply("NSMSG_INVALID_OPTION", discrim
->setwhat
);
4375 } else if (!irccasecmp(argv
[i
], "setvalue")) {
4376 discrim
->setval
= argv
[++i
];
4377 } else if (!irccasecmp(argv
[i
], "hostmask")) {
4379 if (!irccasecmp(argv
[i
], "exact")) {
4380 if (i
== argc
- 1) {
4381 reply("MSG_MISSING_PARAMS", argv
[i
]);
4384 discrim
->hostmask_type
= EXACT
;
4385 } else if (!irccasecmp(argv
[i
], "subset")) {
4386 if (i
== argc
- 1) {
4387 reply("MSG_MISSING_PARAMS", argv
[i
]);
4390 discrim
->hostmask_type
= SUBSET
;
4391 } else if (!irccasecmp(argv
[i
], "superset")) {
4392 if (i
== argc
- 1) {
4393 reply("MSG_MISSING_PARAMS", argv
[i
]);
4396 discrim
->hostmask_type
= SUPERSET
;
4397 } else if (!irccasecmp(argv
[i
], "lastquit") || !irccasecmp(argv
[i
], "lastauth")) {
4398 if (i
== argc
- 1) {
4399 reply("MSG_MISSING_PARAMS", argv
[i
]);
4402 discrim
->hostmask_type
= LASTQUIT
;
4405 discrim
->hostmask_type
= SUPERSET
;
4407 discrim
->hostmask
= argv
[++i
];
4408 } else if (!irccasecmp(argv
[i
], "handlemask") || !irccasecmp(argv
[i
], "accountmask") || !irccasecmp(argv
[i
], "account")) {
4409 if (!irccasecmp(argv
[++i
], "*")) {
4410 discrim
->handlemask
= 0;
4412 discrim
->handlemask
= argv
[i
];
4414 } else if (!irccasecmp(argv
[i
], "email")) {
4415 if (user
->handle_info
->opserv_level
< nickserv_conf
.email_search_level
) {
4416 reply("MSG_NO_SEARCH_ACCESS", "email");
4418 } else if (!irccasecmp(argv
[++i
], "*")) {
4419 discrim
->emailmask
= 0;
4421 discrim
->emailmask
= argv
[i
];
4423 } else if (!irccasecmp(argv
[i
], "title")) {
4424 if (!irccasecmp(argv
[++i
], "*")) {
4425 discrim
->titlemask
= 0;
4427 discrim
->titlemask
= argv
[i
];
4429 } else if (!irccasecmp(argv
[i
], "access")) {
4430 const char *cmp
= argv
[++i
];
4431 if (cmp
[0] == '<') {
4432 if (discrim
->min_level
== 0) discrim
->min_level
= 1;
4433 if (cmp
[1] == '=') {
4434 discrim
->max_level
= strtoul(cmp
+2, NULL
, 0);
4436 discrim
->max_level
= strtoul(cmp
+1, NULL
, 0) - 1;
4438 } else if (cmp
[0] == '=') {
4439 discrim
->min_level
= discrim
->max_level
= strtoul(cmp
+1, NULL
, 0);
4440 } else if (cmp
[0] == '>') {
4441 if (cmp
[1] == '=') {
4442 discrim
->min_level
= strtoul(cmp
+2, NULL
, 0);
4444 discrim
->min_level
= strtoul(cmp
+1, NULL
, 0) + 1;
4447 reply("MSG_INVALID_CRITERIA", cmp
);
4449 } else if (!irccasecmp(argv
[i
], "karma")) {
4450 const char *cmp
= argv
[++i
];
4451 if (cmp
[0] == '<') {
4452 if (cmp
[1] == '=') {
4453 discrim
->max_karma
= strtoul(cmp
+2, NULL
, 0);
4455 discrim
->max_karma
= strtoul(cmp
+1, NULL
, 0) - 1;
4457 } else if (cmp
[0] == '=') {
4458 discrim
->min_karma
= discrim
->max_karma
= strtoul(cmp
+1, NULL
, 0);
4459 } else if (cmp
[0] == '>') {
4460 if (cmp
[1] == '=') {
4461 discrim
->min_karma
= strtoul(cmp
+2, NULL
, 0);
4463 discrim
->min_karma
= strtoul(cmp
+1, NULL
, 0) + 1;
4466 send_message(user
, nickserv
, "MSG_INVALID_CRITERIA", cmp
);
4469 } else if (nickserv_conf
.ldap_enable
&& !irccasecmp(argv
[i
], "inldap")) {
4471 if(true_string(argv
[i
])) {
4472 discrim
->inldap
= 1;
4474 else if (false_string(argv
[i
])) {
4475 discrim
->inldap
= 0;
4478 reply("MSG_INVALID_BINARY", argv
[i
]);
4482 reply("MSG_INVALID_CRITERIA", argv
[i
]);
4493 nickserv_discrim_match(struct nickserv_discrim
*discrim
, struct handle_info
*hi
)
4497 if (hi
->fakehost
&& (hi
->fakehost
[0] == '.'))
4498 title
= hi
->fakehost
+ 1;
4500 if (((discrim
->flags_on
& hi
->flags
) != discrim
->flags_on
)
4501 || (discrim
->flags_off
& hi
->flags
)
4502 || (discrim
->min_registered
> hi
->registered
)
4503 || (discrim
->max_registered
< hi
->registered
)
4504 || (discrim
->lastseen
< (hi
->users
?now
:hi
->lastseen
))
4505 || (discrim
->handlemask
&& !match_ircglob(hi
->handle
, discrim
->handlemask
))
4506 || (discrim
->emailmask
&& (!hi
->email_addr
|| !match_ircglob(hi
->email_addr
, discrim
->emailmask
)))
4507 || (discrim
->titlemask
&& (!title
|| !match_ircglob(title
, discrim
->titlemask
)))
4508 || (discrim
->min_level
> hi
->opserv_level
)
4509 || (discrim
->max_level
< hi
->opserv_level
)
4510 || (discrim
->min_karma
> hi
->karma
)
4511 || (discrim
->max_karma
< hi
->karma
)
4515 if (discrim
->hostmask
) {
4517 for (i
=0; i
<hi
->masks
->used
; i
++) {
4518 const char *mask
= hi
->masks
->list
[i
];
4519 if ((discrim
->hostmask_type
== SUBSET
)
4520 && (match_ircglobs(discrim
->hostmask
, mask
))) break;
4521 else if ((discrim
->hostmask_type
== EXACT
)
4522 && !irccasecmp(discrim
->hostmask
, mask
)) break;
4523 else if ((discrim
->hostmask_type
== SUPERSET
)
4524 && (match_ircglobs(mask
, discrim
->hostmask
))) break;
4525 else if ((discrim
->hostmask_type
== LASTQUIT
)
4526 && (match_ircglobs(discrim
->hostmask
, hi
->last_quit_host
))) break;
4528 if (i
==hi
->masks
->used
) return 0;
4530 if (discrim
->nickmask
) {
4531 struct nick_info
*nick
= hi
->nicks
;
4533 if (match_ircglob(nick
->nick
, discrim
->nickmask
)) break;
4536 if (!nick
) return 0;
4539 if(nickserv_conf
.ldap_enable
&& discrim
->inldap
!= 2) {
4541 rc
= ldap_get_user_info(hi
->handle
, NULL
);
4542 if(discrim
->inldap
== 1 && rc
!= LDAP_SUCCESS
)
4544 if(discrim
->inldap
== 0 && rc
== LDAP_SUCCESS
)
4553 nickserv_discrim_search(struct nickserv_discrim
*discrim
, discrim_search_func dsf
, struct userNode
*source
)
4555 dict_iterator_t it
, next
;
4556 unsigned int matched
;
4558 for (it
= dict_first(nickserv_handle_dict
), matched
= 0;
4559 it
&& (matched
< discrim
->limit
);
4561 next
= iter_next(it
);
4562 if (nickserv_discrim_match(discrim
, iter_data(it
))) {
4563 dsf(source
, iter_data(it
), discrim
);
4571 search_print_func(struct userNode
*source
, struct handle_info
*match
, UNUSED_ARG(struct nickserv_discrim
*discrim
))
4573 send_message(source
, nickserv
, "NSMSG_SEARCH_MATCH", match
->handle
);
4577 search_count_func(UNUSED_ARG(struct userNode
*source
), UNUSED_ARG(struct handle_info
*match
), UNUSED_ARG(struct nickserv_discrim
*discrim
))
4582 search_unregister_func (struct userNode
*source
, struct handle_info
*match
, UNUSED_ARG(struct nickserv_discrim
*discrim
))
4584 if (oper_has_access(source
, nickserv
, match
->opserv_level
, 0))
4585 nickserv_unregister_handle(match
, source
, nickserv
); // XXX nickserv hard coded
4590 search_add2ldap_func (struct userNode
*source
, struct handle_info
*match
, UNUSED_ARG(struct nickserv_discrim
*discrim
))
4593 if(match
->email_addr
&& match
->passwd
&& match
->handle
) {
4594 rc
= ldap_do_add(match
->handle
, match
->passwd
, match
->email_addr
);
4595 if(rc
!= LDAP_SUCCESS
) {
4596 send_message(source
, nickserv
, "NSMSG_LDAP_FAIL_ADD", match
->handle
, ldap_err2string(rc
));
4603 search_set_func (struct userNode
*source
, struct handle_info
*match
, struct nickserv_discrim
*discrim
)
4608 if (!(opt
= dict_find(nickserv_opt_dict
, discrim
->setwhat
, NULL
))) {
4612 oargv
[0] = (char *)discrim
->setwhat
;
4613 oargv
[1] = (char *)discrim
->setval
;
4615 opt(discrim
->cmd
, source
, match
, 1, 1, 2, oargv
);
4619 nickserv_sort_accounts_by_access(const void *a
, const void *b
)
4621 const struct handle_info
*hi_a
= *(const struct handle_info
**)a
;
4622 const struct handle_info
*hi_b
= *(const struct handle_info
**)b
;
4623 if (hi_a
->opserv_level
!= hi_b
->opserv_level
)
4624 return hi_b
->opserv_level
- hi_a
->opserv_level
;
4625 return irccasecmp(hi_a
->handle
, hi_b
->handle
);
4629 nickserv_show_oper_accounts(struct userNode
*user
, struct svccmd
*cmd
)
4631 struct handle_info_list hil
;
4632 struct helpfile_table tbl
;
4637 memset(&hil
, 0, sizeof(hil
));
4638 for (it
= dict_first(nickserv_handle_dict
); it
; it
= iter_next(it
)) {
4639 struct handle_info
*hi
= iter_data(it
);
4640 if (hi
->opserv_level
)
4641 handle_info_list_append(&hil
, hi
);
4643 qsort(hil
.list
, hil
.used
, sizeof(hil
.list
[0]), nickserv_sort_accounts_by_access
);
4644 tbl
.length
= hil
.used
+ 1;
4646 tbl
.flags
= TABLE_NO_FREE
| TABLE_REPEAT_ROWS
| TABLE_REPEAT_HEADERS
;
4647 tbl
.contents
= malloc(tbl
.length
* sizeof(tbl
.contents
[0]));
4648 tbl
.contents
[0] = ary
= malloc(tbl
.width
* sizeof(ary
[0]));
4651 for (ii
= 0; ii
< hil
.used
; ) {
4652 ary
= malloc(tbl
.width
* sizeof(ary
[0]));
4653 ary
[0] = hil
.list
[ii
]->handle
;
4654 ary
[1] = strtab(hil
.list
[ii
]->opserv_level
);
4655 tbl
.contents
[++ii
] = ary
;
4657 table_send(cmd
->parent
->bot
, user
->nick
, 0, NULL
, tbl
);
4658 /*reply("MSG_MATCH_COUNT", hil.used); */
4659 for (ii
= 0; ii
< hil
.used
; ii
++)
4660 free(tbl
.contents
[ii
]);
4665 static NICKSERV_FUNC(cmd_search
)
4667 struct nickserv_discrim
*discrim
;
4668 discrim_search_func action
;
4669 struct svccmd
*subcmd
;
4670 unsigned int matches
;
4673 NICKSERV_MIN_PARMS(3);
4674 sprintf(buf
, "search %s", argv
[1]);
4675 subcmd
= dict_find(nickserv_service
->commands
, buf
, NULL
);
4676 if (!irccasecmp(argv
[1], "print"))
4677 action
= search_print_func
;
4678 else if (!irccasecmp(argv
[1], "count"))
4679 action
= search_count_func
;
4680 else if (!irccasecmp(argv
[1], "unregister"))
4681 action
= search_unregister_func
;
4682 else if (!irccasecmp(argv
[1], "set"))
4683 action
= search_set_func
;
4685 else if (nickserv_conf
.ldap_enable
&& !irccasecmp(argv
[1], "add2ldap"))
4686 action
= search_add2ldap_func
;
4689 reply("NSMSG_INVALID_ACTION", argv
[1]);
4693 if (subcmd
&& !svccmd_can_invoke(user
, nickserv
, subcmd
, NULL
, SVCCMD_NOISY
))
4696 discrim
= nickserv_discrim_create(cmd
, user
, argc
-2, argv
+2);
4700 if (action
== search_print_func
)
4701 reply("NSMSG_ACCOUNT_SEARCH_RESULTS");
4702 else if (action
== search_count_func
)
4703 discrim
->limit
= INT_MAX
;
4704 else if ((action
== search_set_func
) && (!(discrim
->setwhat
) || !(discrim
->setval
)))
4705 return reply("MSG_MISSING_PARAMS", argv
[1]);
4707 matches
= nickserv_discrim_search(discrim
, action
, user
);
4710 reply("MSG_MATCH_COUNT", matches
);
4712 reply("MSG_NO_MATCHES");
4718 static MODCMD_FUNC(cmd_checkpass
)
4720 struct handle_info
*hi
;
4722 NICKSERV_MIN_PARMS(3);
4723 if (!(hi
= get_handle_info(argv
[1]))) {
4724 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
4727 if (checkpass(argv
[2], hi
->passwd
))
4728 reply("CHECKPASS_YES");
4730 reply("CHECKPASS_NO");
4735 static MODCMD_FUNC(cmd_checkemail
)
4737 struct handle_info
*hi
;
4739 NICKSERV_MIN_PARMS(3);
4740 if (!(hi
= modcmd_get_handle_info(user
, argv
[1]))) {
4743 if (!hi
->email_addr
)
4744 reply("CHECKEMAIL_NOT_SET");
4745 else if (!irccasecmp(argv
[2], hi
->email_addr
))
4746 reply("CHECKEMAIL_YES");
4748 reply("CHECKEMAIL_NO");
4753 nickserv_db_read_handle(char *handle
, dict_t obj
)
4756 struct string_list
*masks
, *sslfps
, *slist
, *ignores
;
4757 struct handle_info
*hi
;
4758 struct userNode
*authed_users
;
4759 struct userData
*channel_list
;
4762 unsigned long int id
;
4765 char *setter
, *note
;
4768 str
= database_get_data(obj
, KEY_ID
, RECDB_QSTRING
);
4769 id
= str
? strtoul(str
, NULL
, 0) : 0;
4770 str
= database_get_data(obj
, KEY_PASSWD
, RECDB_QSTRING
);
4772 log_module(NS_LOG
, LOG_WARNING
, "did not find a password for %s -- skipping user.", handle
);
4775 if ((hi
= get_handle_info(handle
))) {
4776 authed_users
= hi
->users
;
4777 channel_list
= hi
->channels
;
4779 hi
->channels
= NULL
;
4780 dict_remove(nickserv_handle_dict
, hi
->handle
);
4782 authed_users
= NULL
;
4783 channel_list
= NULL
;
4785 if(nickserv_conf
.force_handles_lowercase
)
4786 irc_strtolower(handle
);
4787 hi
= register_handle(handle
, str
, id
);
4789 hi
->users
= authed_users
;
4790 while (authed_users
) {
4791 authed_users
->handle_info
= hi
;
4792 authed_users
= authed_users
->next_authed
;
4795 hi
->channels
= channel_list
;
4796 masks
= database_get_data(obj
, KEY_MASKS
, RECDB_STRING_LIST
);
4797 hi
->masks
= masks
? string_list_copy(masks
) : alloc_string_list(1);
4798 sslfps
= database_get_data(obj
, KEY_SSLFPS
, RECDB_STRING_LIST
);
4799 hi
->sslfps
= sslfps
? string_list_copy(sslfps
) : alloc_string_list(1);
4800 ignores
= database_get_data(obj
, KEY_IGNORES
, RECDB_STRING_LIST
);
4801 hi
->ignores
= ignores
? string_list_copy(ignores
) : alloc_string_list(1);
4802 str
= database_get_data(obj
, KEY_MAXLOGINS
, RECDB_QSTRING
);
4803 hi
->maxlogins
= str
? strtoul(str
, NULL
, 0) : 0;
4804 str
= database_get_data(obj
, KEY_LANGUAGE
, RECDB_QSTRING
);
4805 hi
->language
= language_find(str
? str
: "C");
4806 str
= database_get_data(obj
, KEY_OPSERV_LEVEL
, RECDB_QSTRING
);
4807 hi
->opserv_level
= str
? strtoul(str
, NULL
, 0) : 0;
4808 str
= database_get_data(obj
, KEY_INFO
, RECDB_QSTRING
);
4810 hi
->infoline
= strdup(str
);
4811 str
= database_get_data(obj
, KEY_REGISTER_ON
, RECDB_QSTRING
);
4812 hi
->registered
= str
? (time_t)strtoul(str
, NULL
, 0) : now
;
4813 str
= database_get_data(obj
, KEY_LAST_SEEN
, RECDB_QSTRING
);
4814 hi
->lastseen
= str
? (time_t)strtoul(str
, NULL
, 0) : hi
->registered
;
4815 str
= database_get_data(obj
, KEY_KARMA
, RECDB_QSTRING
);
4816 hi
->karma
= str
? strtoul(str
, NULL
, 0) : 0;
4817 /* We want to read the nicks even if disable_nicks is set. This is so
4818 * that we don't lose the nick data entirely. */
4819 obj2
= database_get_data(obj
, KEY_NICKS_EX
, RECDB_OBJECT
);
4820 for(it
= dict_first(obj2
); it
; it
= iter_next(it
))
4822 struct record_data
*rd
= iter_data(it
);
4823 struct nick_info
* ni
;
4825 register_nick(iter_key(it
), hi
);
4826 ni
= get_nick_info(iter_key(it
));
4831 str
= database_get_data(rd
->d
.object
, KEY_REGISTER_ON
, RECDB_QSTRING
);
4832 ni
->registered
= str
? (time_t)strtoul(str
, NULL
, 0) : now
;
4833 str
= database_get_data(rd
->d
.object
, KEY_LAST_SEEN
, RECDB_QSTRING
);
4834 ni
->lastseen
= str
? (time_t)strtoul(str
, NULL
, 0) : ni
->registered
;
4837 slist
= database_get_data(obj
, KEY_NICKS
, RECDB_STRING_LIST
);
4839 for (ii
=0; ii
<slist
->used
; ii
++) {
4840 struct nick_info
* ni
;
4842 register_nick(slist
->list
[ii
], hi
);
4843 ni
= get_nick_info(slist
->list
[ii
]);
4848 ni
->registered
= hi
->registered
;
4849 ni
->lastseen
= ni
->registered
;
4853 str
= database_get_data(obj
, KEY_FLAGS
, RECDB_QSTRING
);
4855 for (ii
=0; str
[ii
]; ii
++)
4856 hi
->flags
|= 1 << (handle_inverse_flags
[(unsigned char)str
[ii
]] - 1);
4858 str
= database_get_data(obj
, KEY_USERLIST_STYLE
, RECDB_QSTRING
);
4859 hi
->userlist_style
= str
? str
[0] : HI_DEFAULT_STYLE
;
4860 str
= database_get_data(obj
, KEY_ANNOUNCEMENTS
, RECDB_QSTRING
);
4861 hi
->announcements
= str
? str
[0] : '?';
4862 str
= database_get_data(obj
, KEY_SCREEN_WIDTH
, RECDB_QSTRING
);
4863 hi
->screen_width
= str
? strtoul(str
, NULL
, 0) : 0;
4864 str
= database_get_data(obj
, KEY_TABLE_WIDTH
, RECDB_QSTRING
);
4865 hi
->table_width
= str
? strtoul(str
, NULL
, 0) : 0;
4866 str
= database_get_data(obj
, KEY_LAST_QUIT_HOST
, RECDB_QSTRING
);
4868 str
= database_get_data(obj
, KEY_LAST_AUTHED_HOST
, RECDB_QSTRING
);
4870 safestrncpy(hi
->last_quit_host
, str
, sizeof(hi
->last_quit_host
));
4871 str
= database_get_data(obj
, KEY_EMAIL_ADDR
, RECDB_QSTRING
);
4873 nickserv_set_email_addr(hi
, str
);
4874 str
= database_get_data(obj
, KEY_EPITHET
, RECDB_QSTRING
);
4876 hi
->epithet
= strdup(str
);
4877 subdb
= database_get_data(obj
, KEY_NOTE_NOTE
, RECDB_OBJECT
);
4879 setter
= database_get_data(subdb
, KEY_NOTE_SETTER
, RECDB_QSTRING
);
4880 str
= database_get_data(subdb
, KEY_NOTE_DATE
, RECDB_QSTRING
);
4881 date
= str
? (time_t)strtoul(str
, NULL
, 0) : now
;
4882 note
= database_get_data(subdb
, KEY_NOTE_NOTE
, RECDB_QSTRING
);
4883 if (setter
&& date
&& note
)
4885 if (!(hi
->note
= nickserv_add_note(setter
, date
, note
)))
4890 str
= database_get_data(obj
, KEY_FAKEHOST
, RECDB_QSTRING
);
4892 hi
->fakehost
= strdup(str
);
4894 subdb
= database_get_data(obj
, KEY_COOKIE
, RECDB_OBJECT
);
4896 const char *data
, *type
, *expires
, *cookie_str
;
4897 struct handle_cookie
*cookie
;
4899 cookie
= calloc(1, sizeof(*cookie
));
4900 type
= database_get_data(subdb
, KEY_COOKIE_TYPE
, RECDB_QSTRING
);
4901 data
= database_get_data(subdb
, KEY_COOKIE_DATA
, RECDB_QSTRING
);
4902 expires
= database_get_data(subdb
, KEY_COOKIE_EXPIRES
, RECDB_QSTRING
);
4903 cookie_str
= database_get_data(subdb
, KEY_COOKIE
, RECDB_QSTRING
);
4904 if (!type
|| !expires
|| !cookie_str
) {
4905 log_module(NS_LOG
, LOG_ERROR
, "Missing field(s) from cookie for account %s; dropping cookie.", hi
->handle
);
4908 if (!irccasecmp(type
, KEY_ACTIVATION
))
4909 cookie
->type
= ACTIVATION
;
4910 else if (!irccasecmp(type
, KEY_PASSWORD_CHANGE
))
4911 cookie
->type
= PASSWORD_CHANGE
;
4912 else if (!irccasecmp(type
, KEY_EMAIL_CHANGE
))
4913 cookie
->type
= EMAIL_CHANGE
;
4914 else if (!irccasecmp(type
, KEY_ALLOWAUTH
))
4915 cookie
->type
= ALLOWAUTH
;
4917 log_module(NS_LOG
, LOG_ERROR
, "Invalid cookie type %s for account %s; dropping cookie.", type
, handle
);
4920 cookie
->expires
= strtoul(expires
, NULL
, 0);
4921 if (cookie
->expires
< now
)
4924 cookie
->data
= strdup(data
);
4925 safestrncpy(cookie
->cookie
, cookie_str
, sizeof(cookie
->cookie
));
4929 nickserv_bake_cookie(cookie
);
4931 nickserv_free_cookie(cookie
);
4936 nickserv_saxdb_read(dict_t db
) {
4938 struct record_data
*rd
;
4941 for (it
=dict_first(db
); it
; it
=iter_next(it
)) {
4943 handle
= strdup(iter_key(it
));
4944 nickserv_db_read_handle(handle
, rd
->d
.object
);
4950 static NICKSERV_FUNC(cmd_mergedb
)
4952 struct timeval start
, stop
;
4955 NICKSERV_MIN_PARMS(2);
4956 gettimeofday(&start
, NULL
);
4957 if (!(db
= parse_database(argv
[1]))) {
4958 reply("NSMSG_DB_UNREADABLE", argv
[1]);
4961 nickserv_saxdb_read(db
);
4963 gettimeofday(&stop
, NULL
);
4964 stop
.tv_sec
-= start
.tv_sec
;
4965 stop
.tv_usec
-= start
.tv_usec
;
4966 if (stop
.tv_usec
< 0) {
4968 stop
.tv_usec
+= 1000000;
4970 reply("NSMSG_DB_MERGED", argv
[1], stop
.tv_sec
, stop
.tv_usec
/1000);
4975 expire_handles(UNUSED_ARG(void *data
))
4977 dict_iterator_t it
, next
;
4979 struct handle_info
*hi
;
4981 for (it
=dict_first(nickserv_handle_dict
); it
; it
=next
) {
4982 next
= iter_next(it
);
4984 if ((hi
->opserv_level
> 0)
4986 || HANDLE_FLAGGED(hi
, FROZEN
)
4987 || HANDLE_FLAGGED(hi
, NODELETE
)) {
4990 expiry
= hi
->channels
? nickserv_conf
.handle_expire_delay
: nickserv_conf
.nochan_handle_expire_delay
;
4991 if ((now
- hi
->lastseen
) > expiry
) {
4992 log_module(NS_LOG
, LOG_INFO
, "Expiring account %s for inactivity.", hi
->handle
);
4993 nickserv_unregister_handle(hi
, NULL
, NULL
);
4997 if (nickserv_conf
.handle_expire_frequency
)
4998 timeq_add(now
+ nickserv_conf
.handle_expire_frequency
, expire_handles
, NULL
);
5002 expire_nicks(UNUSED_ARG(void *data
))
5004 dict_iterator_t it
, next
;
5005 time_t expiry
= nickserv_conf
.nick_expire_delay
;
5006 struct nick_info
*ni
;
5007 struct userNode
*ui
;
5009 if (!(nickserv_conf
.expire_nicks
))
5012 for (it
=dict_first(nickserv_nick_dict
); it
; it
=next
) {
5013 next
= iter_next(it
);
5015 if ((ni
->owner
->opserv_level
> 0)
5016 || ((ui
= GetUserH(ni
->nick
)) && (ui
->handle_info
) && (ui
->handle_info
== ni
->owner
))
5017 || HANDLE_FLAGGED(ni
->owner
, FROZEN
)
5018 || HANDLE_FLAGGED(ni
->owner
, NODELETE
)) {
5021 if ((now
- ni
->lastseen
) > expiry
) {
5022 log_module(NS_LOG
, LOG_INFO
, "Expiring nick %s for inactivity.", ni
->nick
);
5027 if (nickserv_conf
.nick_expire_frequency
&& nickserv_conf
.expire_nicks
)
5028 timeq_add(now
+ nickserv_conf
.nick_expire_frequency
, expire_nicks
, NULL
);
5032 nickserv_load_dict(const char *fname
)
5036 if (!(file
= fopen(fname
, "r"))) {
5037 log_module(NS_LOG
, LOG_ERROR
, "Unable to open dictionary file %s: %s", fname
, strerror(errno
));
5040 while (fgets(line
, sizeof(line
), file
)) {
5043 if (line
[strlen(line
)-1] == '\n')
5044 line
[strlen(line
)-1] = 0;
5045 dict_insert(nickserv_conf
.weak_password_dict
, strdup(line
), NULL
);
5048 log_module(NS_LOG
, LOG_INFO
, "Loaded %d words into weak password dictionary.", dict_size(nickserv_conf
.weak_password_dict
));
5051 static enum reclaim_action
5052 reclaim_action_from_string(const char *str
) {
5054 return RECLAIM_NONE
;
5055 else if (!irccasecmp(str
, "warn"))
5056 return RECLAIM_WARN
;
5057 else if (!irccasecmp(str
, "svsnick"))
5058 return RECLAIM_SVSNICK
;
5059 else if (!irccasecmp(str
, "kill"))
5060 return RECLAIM_KILL
;
5062 return RECLAIM_NONE
;
5066 nickserv_conf_read(void)
5068 dict_t conf_node
, child
;
5071 struct string_list
*strlist
;
5073 if (!(conf_node
= conf_get_data(NICKSERV_CONF_NAME
, RECDB_OBJECT
))) {
5074 log_module(NS_LOG
, LOG_ERROR
, "config node `%s' is missing or has wrong type.", NICKSERV_CONF_NAME
);
5077 str
= database_get_data(conf_node
, KEY_VALID_HANDLE_REGEX
, RECDB_QSTRING
);
5079 str
= database_get_data(conf_node
, KEY_VALID_ACCOUNT_REGEX
, RECDB_QSTRING
);
5080 if (nickserv_conf
.valid_handle_regex_set
)
5081 regfree(&nickserv_conf
.valid_handle_regex
);
5083 int err
= regcomp(&nickserv_conf
.valid_handle_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
5084 nickserv_conf
.valid_handle_regex_set
= !err
;
5085 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_account_regex (error %d)", err
);
5087 nickserv_conf
.valid_handle_regex_set
= 0;
5089 str
= database_get_data(conf_node
, KEY_VALID_NICK_REGEX
, RECDB_QSTRING
);
5090 if (nickserv_conf
.valid_nick_regex_set
)
5091 regfree(&nickserv_conf
.valid_nick_regex
);
5093 int err
= regcomp(&nickserv_conf
.valid_nick_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
5094 nickserv_conf
.valid_nick_regex_set
= !err
;
5095 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_nick_regex (error %d)", err
);
5097 nickserv_conf
.valid_nick_regex_set
= 0;
5099 str
= database_get_data(conf_node
, KEY_VALID_FAKEHOST_REGEX
, RECDB_QSTRING
);
5100 if (nickserv_conf
.valid_fakehost_regex_set
)
5101 regfree(&nickserv_conf
.valid_fakehost_regex
);
5103 int err
= regcomp(&nickserv_conf
.valid_fakehost_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
5104 nickserv_conf
.valid_fakehost_regex_set
= !err
;
5105 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_fakehost_regex (error %d)", err
);
5107 nickserv_conf
.valid_fakehost_regex_set
= 0;
5109 str
= database_get_data(conf_node
, KEY_NICKS_PER_HANDLE
, RECDB_QSTRING
);
5111 str
= database_get_data(conf_node
, KEY_NICKS_PER_ACCOUNT
, RECDB_QSTRING
);
5112 nickserv_conf
.nicks_per_handle
= str
? strtoul(str
, NULL
, 0) : 4;
5113 str
= database_get_data(conf_node
, KEY_DISABLE_NICKS
, RECDB_QSTRING
);
5114 nickserv_conf
.disable_nicks
= str
? strtoul(str
, NULL
, 0) : 0;
5115 str
= database_get_data(conf_node
, KEY_DEFAULT_HOSTMASK
, RECDB_QSTRING
);
5116 nickserv_conf
.default_hostmask
= str
? !disabled_string(str
) : 0;
5117 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_LENGTH
, RECDB_QSTRING
);
5118 nickserv_conf
.password_min_length
= str
? strtoul(str
, NULL
, 0) : 0;
5119 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_DIGITS
, RECDB_QSTRING
);
5120 nickserv_conf
.password_min_digits
= str
? strtoul(str
, NULL
, 0) : 0;
5121 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_UPPER
, RECDB_QSTRING
);
5122 nickserv_conf
.password_min_upper
= str
? strtoul(str
, NULL
, 0) : 0;
5123 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_LOWER
, RECDB_QSTRING
);
5124 nickserv_conf
.password_min_lower
= str
? strtoul(str
, NULL
, 0) : 0;
5125 str
= database_get_data(conf_node
, KEY_DB_BACKUP_FREQ
, RECDB_QSTRING
);
5126 nickserv_conf
.db_backup_frequency
= str
? ParseInterval(str
) : 7200;
5127 str
= database_get_data(conf_node
, KEY_MODOPER_LEVEL
, RECDB_QSTRING
);
5128 nickserv_conf
.modoper_level
= str
? strtoul(str
, NULL
, 0) : 900;
5129 str
= database_get_data(conf_node
, KEY_SET_EPITHET_LEVEL
, RECDB_QSTRING
);
5130 nickserv_conf
.set_epithet_level
= str
? strtoul(str
, NULL
, 0) : 1;
5131 str
= database_get_data(conf_node
, KEY_SET_TITLE_LEVEL
, RECDB_QSTRING
);
5132 nickserv_conf
.set_title_level
= str
? strtoul(str
, NULL
, 0) : 900;
5133 str
= database_get_data(conf_node
, KEY_SET_FAKEHOST_LEVEL
, RECDB_QSTRING
);
5134 nickserv_conf
.set_fakehost_level
= str
? strtoul(str
, NULL
, 0) : 1000;
5135 str
= database_get_data(conf_node
, KEY_HANDLE_EXPIRE_FREQ
, RECDB_QSTRING
);
5137 str
= database_get_data(conf_node
, KEY_ACCOUNT_EXPIRE_FREQ
, RECDB_QSTRING
);
5138 nickserv_conf
.handle_expire_frequency
= str
? ParseInterval(str
) : 86400;
5139 str
= database_get_data(conf_node
, KEY_HANDLE_EXPIRE_DELAY
, RECDB_QSTRING
);
5141 str
= database_get_data(conf_node
, KEY_ACCOUNT_EXPIRE_DELAY
, RECDB_QSTRING
);
5142 nickserv_conf
.handle_expire_delay
= str
? ParseInterval(str
) : 86400*30;
5143 str
= database_get_data(conf_node
, KEY_NOCHAN_HANDLE_EXPIRE_DELAY
, RECDB_QSTRING
);
5145 str
= database_get_data(conf_node
, KEY_NOCHAN_ACCOUNT_EXPIRE_DELAY
, RECDB_QSTRING
);
5146 nickserv_conf
.nochan_handle_expire_delay
= str
? ParseInterval(str
) : 86400*15;
5147 str
= database_get_data(conf_node
, "warn_clone_auth", RECDB_QSTRING
);
5148 nickserv_conf
.warn_clone_auth
= str
? !disabled_string(str
) : 1;
5149 str
= database_get_data(conf_node
, "default_maxlogins", RECDB_QSTRING
);
5150 nickserv_conf
.default_maxlogins
= str
? strtoul(str
, NULL
, 0) : 2;
5151 str
= database_get_data(conf_node
, "hard_maxlogins", RECDB_QSTRING
);
5152 nickserv_conf
.hard_maxlogins
= str
? strtoul(str
, NULL
, 0) : 10;
5153 str
= database_get_data(conf_node
, KEY_OUNREGISTER_INACTIVE
, RECDB_QSTRING
);
5154 nickserv_conf
.ounregister_inactive
= str
? ParseInterval(str
) : 86400*28;
5155 str
= database_get_data(conf_node
, KEY_OUNREGISTER_FLAGS
, RECDB_QSTRING
);
5158 nickserv_conf
.ounregister_flags
= 0;
5160 unsigned int pos
= handle_inverse_flags
[(unsigned char)*str
];
5163 nickserv_conf
.ounregister_flags
|= 1 << (pos
- 1);
5165 if (!nickserv_conf
.disable_nicks
) {
5166 str
= database_get_data(conf_node
, "reclaim_action", RECDB_QSTRING
);
5167 nickserv_conf
.reclaim_action
= str
? reclaim_action_from_string(str
) : RECLAIM_NONE
;
5168 str
= database_get_data(conf_node
, "warn_nick_owned", RECDB_QSTRING
);
5169 nickserv_conf
.warn_nick_owned
= str
? enabled_string(str
) : 0;
5170 str
= database_get_data(conf_node
, "auto_reclaim_action", RECDB_QSTRING
);
5171 nickserv_conf
.auto_reclaim_action
= str
? reclaim_action_from_string(str
) : RECLAIM_NONE
;
5172 str
= database_get_data(conf_node
, "auto_reclaim_delay", RECDB_QSTRING
);
5173 nickserv_conf
.auto_reclaim_delay
= str
? ParseInterval(str
) : 0;
5174 str
= database_get_data(conf_node
, KEY_NICK_EXPIRE_FREQ
, RECDB_QSTRING
);
5175 nickserv_conf
.nick_expire_frequency
= str
? ParseInterval(str
) : 86400;
5176 str
= database_get_data(conf_node
, KEY_NICK_EXPIRE_DELAY
, RECDB_QSTRING
);
5177 nickserv_conf
.nick_expire_delay
= str
? ParseInterval(str
) : 86400*30;
5178 str
= database_get_data(conf_node
, "expire_nicks", RECDB_QSTRING
);
5179 nickserv_conf
.expire_nicks
= str
? enabled_string(str
) : 0;
5181 child
= database_get_data(conf_node
, KEY_FLAG_LEVELS
, RECDB_OBJECT
);
5182 for (it
=dict_first(child
); it
; it
=iter_next(it
)) {
5183 const char *key
= iter_key(it
), *value
;
5187 if (!strncasecmp(key
, "uc_", 3))
5188 flag
= toupper(key
[3]);
5189 else if (!strncasecmp(key
, "lc_", 3))
5190 flag
= tolower(key
[3]);
5194 if ((pos
= handle_inverse_flags
[flag
])) {
5195 value
= GET_RECORD_QSTRING((struct record_data
*)iter_data(it
));
5196 flag_access_levels
[pos
- 1] = strtoul(value
, NULL
, 0);
5199 if (nickserv_conf
.weak_password_dict
)
5200 dict_delete(nickserv_conf
.weak_password_dict
);
5201 nickserv_conf
.weak_password_dict
= dict_new();
5202 dict_set_free_keys(nickserv_conf
.weak_password_dict
, free
);
5203 dict_insert(nickserv_conf
.weak_password_dict
, strdup("password"), NULL
);
5204 dict_insert(nickserv_conf
.weak_password_dict
, strdup("<password>"), NULL
);
5205 str
= database_get_data(conf_node
, KEY_DICT_FILE
, RECDB_QSTRING
);
5207 nickserv_load_dict(str
);
5208 str
= database_get_data(conf_node
, KEY_NICK
, RECDB_QSTRING
);
5209 if (nickserv
&& str
)
5210 NickChange(nickserv
, str
, 0);
5211 str
= database_get_data(conf_node
, KEY_AUTOGAG_ENABLED
, RECDB_QSTRING
);
5212 nickserv_conf
.autogag_enabled
= str
? strtoul(str
, NULL
, 0) : 1;
5213 str
= database_get_data(conf_node
, KEY_AUTOGAG_DURATION
, RECDB_QSTRING
);
5214 nickserv_conf
.autogag_duration
= str
? ParseInterval(str
) : 1800;
5215 str
= database_get_data(conf_node
, KEY_EMAIL_VISIBLE_LEVEL
, RECDB_QSTRING
);
5216 nickserv_conf
.email_visible_level
= str
? strtoul(str
, NULL
, 0) : 800;
5217 str
= database_get_data(conf_node
, KEY_EMAIL_ENABLED
, RECDB_QSTRING
);
5218 nickserv_conf
.email_enabled
= str
? enabled_string(str
) : 0;
5219 str
= database_get_data(conf_node
, KEY_SYNC_LOG
, RECDB_QSTRING
);
5220 nickserv_conf
.sync_log
= str
? enabled_string(str
) : 0;
5221 str
= database_get_data(conf_node
, KEY_COOKIE_TIMEOUT
, RECDB_QSTRING
);
5222 nickserv_conf
.cookie_timeout
= str
? ParseInterval(str
) : 24*3600;
5223 str
= database_get_data(conf_node
, KEY_EMAIL_REQUIRED
, RECDB_QSTRING
);
5224 nickserv_conf
.email_required
= (nickserv_conf
.email_enabled
&& str
) ? enabled_string(str
) : 0;
5225 str
= database_get_data(conf_node
, KEY_ACCOUNTS_PER_EMAIL
, RECDB_QSTRING
);
5226 nickserv_conf
.handles_per_email
= str
? strtoul(str
, NULL
, 0) : 1;
5227 str
= database_get_data(conf_node
, KEY_EMAIL_SEARCH_LEVEL
, RECDB_QSTRING
);
5228 nickserv_conf
.email_search_level
= str
? strtoul(str
, NULL
, 0) : 600;
5229 str
= database_get_data(conf_node
, KEY_TITLEHOST_SUFFIX
, RECDB_QSTRING
);
5230 nickserv_conf
.titlehost_suffix
= str
? str
: "example.net";
5232 free_string_list(nickserv_conf
.denied_fakehost_words
);
5233 strlist
= database_get_data(conf_node
, KEY_DENIED_FAKEHOST_WORDS
, RECDB_STRING_LIST
);
5235 strlist
= string_list_copy(strlist
);
5237 strlist
= alloc_string_list(4);
5238 string_list_append(strlist
, strdup("sex"));
5239 string_list_append(strlist
, strdup("fuck"));
5241 nickserv_conf
.denied_fakehost_words
= strlist
;
5243 str
= database_get_data(conf_node
, KEY_DEFAULT_STYLE
, RECDB_QSTRING
);
5244 nickserv_conf
.default_style
= str
? str
[0] : HI_DEFAULT_STYLE
;
5246 str
= database_get_data(conf_node
, KEY_AUTO_OPER
, RECDB_QSTRING
);
5247 nickserv_conf
.auto_oper
= str
? str
: "";
5249 str
= database_get_data(conf_node
, KEY_AUTO_ADMIN
, RECDB_QSTRING
);
5250 nickserv_conf
.auto_admin
= str
? str
: "";
5252 str
= database_get_data(conf_node
, KEY_AUTO_OPER_PRIVS
, RECDB_QSTRING
);
5253 nickserv_conf
.auto_oper_privs
= str
? str
: "";
5255 str
= database_get_data(conf_node
, KEY_AUTO_ADMIN_PRIVS
, RECDB_QSTRING
);
5256 nickserv_conf
.auto_admin_privs
= str
? str
: "";
5258 str
= conf_get_data("server/network", RECDB_QSTRING
);
5259 nickserv_conf
.network_name
= str
? str
: "some IRC network";
5260 if (!nickserv_conf
.auth_policer_params
) {
5261 nickserv_conf
.auth_policer_params
= policer_params_new();
5262 policer_params_set(nickserv_conf
.auth_policer_params
, "size", "5");
5263 policer_params_set(nickserv_conf
.auth_policer_params
, "drain-rate", "0.05");
5265 child
= database_get_data(conf_node
, KEY_AUTH_POLICER
, RECDB_OBJECT
);
5266 for (it
=dict_first(child
); it
; it
=iter_next(it
))
5267 set_policer_param(iter_key(it
), iter_data(it
), nickserv_conf
.auth_policer_params
);
5269 str
= database_get_data(conf_node
, KEY_LDAP_ENABLE
, RECDB_QSTRING
);
5270 nickserv_conf
.ldap_enable
= str
? strtoul(str
, NULL
, 0) : 0;
5272 str
= database_get_data(conf_node
, KEY_FORCE_HANDLES_LOWERCASE
, RECDB_QSTRING
);
5273 nickserv_conf
.force_handles_lowercase
= str
? strtol(str
, NULL
, 0) : 0;
5276 if(nickserv_conf
.ldap_enable
> 0) {
5277 /* ldap is enabled but not compiled in - error out */
5278 log_module(MAIN_LOG
, LOG_ERROR
, "ldap is enabled in config, but not compiled in!");
5279 nickserv_conf
.ldap_enable
= 0;
5285 str
= database_get_data(conf_node
, KEY_LDAP_URI
, RECDB_QSTRING
);
5286 nickserv_conf
.ldap_uri
= str
? str
: "";
5288 str
= database_get_data(conf_node
, KEY_LDAP_BASE
, RECDB_QSTRING
);
5289 nickserv_conf
.ldap_base
= str
? str
: "";
5291 str
= database_get_data(conf_node
, KEY_LDAP_DN_FMT
, RECDB_QSTRING
);
5292 nickserv_conf
.ldap_dn_fmt
= str
? str
: "";
5294 str
= database_get_data(conf_node
, KEY_LDAP_VERSION
, RECDB_QSTRING
);
5295 nickserv_conf
.ldap_version
= str
? strtoul(str
, NULL
, 0) : 3;
5297 str
= database_get_data(conf_node
, KEY_LDAP_AUTOCREATE
, RECDB_QSTRING
);
5298 nickserv_conf
.ldap_autocreate
= str
? strtoul(str
, NULL
, 0) : 0;
5300 str
= database_get_data(conf_node
, KEY_LDAP_TIMEOUT
, RECDB_QSTRING
);
5301 nickserv_conf
.ldap_timeout
= str
? strtoul(str
, NULL
, 0) : 5;
5303 str
= database_get_data(conf_node
, KEY_LDAP_ADMIN_DN
, RECDB_QSTRING
);
5304 nickserv_conf
.ldap_admin_dn
= str
? str
: "";
5306 str
= database_get_data(conf_node
, KEY_LDAP_ADMIN_PASS
, RECDB_QSTRING
);
5307 nickserv_conf
.ldap_admin_pass
= str
? str
: "";
5309 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_ACCOUNT
, RECDB_QSTRING
);
5310 nickserv_conf
.ldap_field_account
= str
? str
: "";
5312 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_PASSWORD
, RECDB_QSTRING
);
5313 nickserv_conf
.ldap_field_password
= str
? str
: "";
5315 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_EMAIL
, RECDB_QSTRING
);
5316 nickserv_conf
.ldap_field_email
= str
? str
: "";
5318 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_OSLEVEL
, RECDB_QSTRING
);
5319 nickserv_conf
.ldap_field_oslevel
= str
? str
: "";
5321 str
= database_get_data(conf_node
, KEY_LDAP_OPER_GROUP_DN
, RECDB_QSTRING
);
5322 nickserv_conf
.ldap_oper_group_dn
= str
? str
: "";
5324 str
= database_get_data(conf_node
, KEY_LDAP_OPER_GROUP_LEVEL
, RECDB_QSTRING
);
5325 nickserv_conf
.ldap_oper_group_level
= str
? strtoul(str
, NULL
, 0) : 99;
5327 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_GROUP_MEMBER
, RECDB_QSTRING
);
5328 nickserv_conf
.ldap_field_group_member
= str
? str
: "";
5330 free_string_list(nickserv_conf
.ldap_object_classes
);
5331 strlist
= database_get_data(conf_node
, KEY_LDAP_OBJECT_CLASSES
, RECDB_STRING_LIST
);
5333 strlist
= string_list_copy(strlist
);
5335 strlist
= alloc_string_list(4);
5336 string_list_append(strlist
, strdup("top"));
5338 nickserv_conf
.ldap_object_classes
= strlist
;
5345 nickserv_reclaim(struct userNode
*user
, struct nick_info
*ni
, enum reclaim_action action
) {
5347 char newnick
[NICKLEN
+1];
5360 send_message(user
, nickserv
, "NSMSG_RECLAIM_WARN", ni
->nick
, ni
->owner
->handle
);
5361 send_message(user
, nickserv
, "NSMSG_RECLAIM_HOWTO", ni
->owner
->handle
, nickserv
->nick
, self
->name
, ni
->owner
->handle
);
5363 case RECLAIM_SVSNICK
:
5365 snprintf(newnick
, sizeof(newnick
), "Guest%d", rand()%10000
);
5366 } while (GetUserH(newnick
));
5367 irc_svsnick(nickserv
, user
, newnick
);
5370 msg
= user_find_message(user
, "NSMSG_RECLAIM_KILL");
5371 DelUser(user
, nickserv
, 1, msg
);
5377 nickserv_reclaim_p(void *data
) {
5378 struct userNode
*user
= data
;
5379 struct nick_info
*ni
= get_nick_info(user
->nick
);
5381 nickserv_reclaim(user
, ni
, nickserv_conf
.auto_reclaim_action
);
5385 check_user_nick(struct userNode
*user
, UNUSED_ARG(void *extra
)) {
5386 struct nick_info
*ni
;
5387 user
->modes
&= ~FLAGS_REGNICK
;
5388 if (!(ni
= get_nick_info(user
->nick
)))
5390 if (user
->handle_info
== ni
->owner
) {
5391 user
->modes
|= FLAGS_REGNICK
;
5395 if (nickserv_conf
.warn_nick_owned
)
5396 send_message(user
, nickserv
, "NSMSG_RECLAIM_WARN", ni
->nick
, ni
->owner
->handle
);
5397 send_message(user
, nickserv
, "NSMSG_RECLAIM_HOWTO", ni
->owner
->handle
, nickserv
->nick
, self
->name
, ni
->owner
->handle
);
5398 if (nickserv_conf
.auto_reclaim_action
== RECLAIM_NONE
)
5400 if (nickserv_conf
.auto_reclaim_delay
)
5401 timeq_add(now
+ nickserv_conf
.auto_reclaim_delay
, nickserv_reclaim_p
, user
);
5403 nickserv_reclaim(user
, ni
, nickserv_conf
.auto_reclaim_action
);
5409 handle_account(struct userNode
*user
, const char *stamp
)
5411 struct handle_info
*hi
;
5414 #ifdef WITH_PROTOCOL_P10
5415 time_t timestamp
= 0;
5417 colon
= strchr(stamp
, ':');
5418 if(colon
&& colon
[1])
5421 timestamp
= atoi(colon
+1);
5423 hi
= dict_find(nickserv_handle_dict
, stamp
, NULL
);
5424 if(hi
&& timestamp
&& hi
->registered
!= timestamp
)
5426 log_module(MAIN_LOG
, LOG_WARNING
, "%s using account %s but timestamp does not match %s is not %s.", user
->nick
, stamp
, ctime(×tamp
),
5427 ctime(&hi
->registered
));
5431 hi
= dict_find(nickserv_id_dict
, stamp
, NULL
);
5432 log_module(MAIN_LOG
, LOG_WARNING
, "Using non-P10 code in accounts, not tested at all!");
5436 if(!hi
&& nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_autocreate
&&
5437 (ldap_user_exists(stamp
) == LDAP_SUCCESS
)) {
5443 /* First attempt to get the email address from LDAP */
5444 if((rc
= ldap_get_user_info(stamp
, &email
) != LDAP_SUCCESS
))
5445 if(nickserv_conf
.email_required
)
5448 /* Now try to register the handle */
5449 if (cont
&& (hi
= nickserv_register(user
, user
, stamp
, NULL
, 1))) {
5450 if(nickserv_conf
.default_hostmask
)
5453 mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
5456 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
5457 string_list_append(hi
->masks
, mask_canonicalized
);
5461 nickserv_set_email_addr(hi
, email
);
5469 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
5472 set_user_handle_info(user
, hi
, 0);
5474 log_module(MAIN_LOG
, LOG_WARNING
, "%s had unknown account stamp %s.", user
->nick
, stamp
);
5479 handle_nick_change(struct userNode
*user
, const char *old_nick
, UNUSED_ARG(void *extra
))
5481 struct handle_info
*hi
;
5483 if ((hi
= dict_find(nickserv_allow_auth_dict
, old_nick
, 0))) {
5484 dict_remove(nickserv_allow_auth_dict
, old_nick
);
5485 dict_insert(nickserv_allow_auth_dict
, user
->nick
, hi
);
5487 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
5488 check_user_nick(user
, NULL
);
5492 nickserv_remove_user(struct userNode
*user
, UNUSED_ARG(struct userNode
*killer
), UNUSED_ARG(const char *why
), UNUSED_ARG(void *extra
))
5494 dict_remove(nickserv_allow_auth_dict
, user
->nick
);
5495 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
5496 set_user_handle_info(user
, NULL
, 0);
5499 static struct modcmd
*
5500 nickserv_define_func(const char *name
, modcmd_func_t func
, int min_level
, int must_auth
, int must_be_qualified
)
5502 if (min_level
> 0) {
5504 sprintf(buf
, "%u", min_level
);
5505 if (must_be_qualified
) {
5506 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "level", buf
, "flags", "+qualified,+loghostmask", NULL
);
5508 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "level", buf
, NULL
);
5510 } else if (min_level
== 0) {
5511 if (must_be_qualified
) {
5512 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+helping", NULL
);
5514 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+helping", NULL
);
5517 if (must_be_qualified
) {
5518 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+qualified,+loghostmask", NULL
);
5520 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), NULL
);
5525 #define SDFLAG_STALE 0x01 /**< SASL session data is stale, delete on next pass. */
5529 struct SASLSession
*next
;
5530 struct SASLSession
*prev
;
5531 struct server
* source
;
5540 struct SASLSession
*saslsessions
= NULL
;
5543 sasl_delete_session(struct SASLSession
*session
)
5552 session
->next
->prev
= session
->prev
;
5554 session
->prev
->next
= session
->next
;
5556 saslsessions
= session
->next
;
5562 sasl_delete_stale(UNUSED_ARG(void *data
))
5566 struct SASLSession
*sess
= NULL
;
5567 struct SASLSession
*nextsess
= NULL
;
5569 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Checking for stale sessions");
5571 for (sess
= saslsessions
; sess
; sess
= nextsess
)
5573 nextsess
= sess
->next
;
5575 if (sess
->flags
& SDFLAG_STALE
)
5578 sasl_delete_session(sess
);
5583 sess
->flags
|= SDFLAG_STALE
;
5588 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Deleted %d stale sessions, %d remaining", delcount
, remcount
);
5590 timeq_add(now
+ 30, sasl_delete_stale
, NULL
);
5594 sasl_get_session(const char *uid
)
5596 struct SASLSession
*sess
;
5598 for (sess
= saslsessions
; sess
; sess
= sess
->next
)
5600 if (!strncmp(sess
->uid
, uid
, 128))
5602 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Found session for %s", sess
->uid
);
5607 sess
= malloc(sizeof(struct SASLSession
));
5608 memset(sess
, 0, sizeof(struct SASLSession
));
5610 strncpy(sess
->uid
, uid
, 128);
5613 timeq_add(now
+ 30, sasl_delete_stale
, NULL
);
5616 saslsessions
->prev
= sess
;
5617 sess
->next
= saslsessions
;
5618 saslsessions
= sess
;
5620 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Created session for %s", sess
->uid
);
5625 sasl_packet(struct SASLSession
*session
)
5627 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Got packet containing: %s", session
->buf
);
5629 if (!session
->mech
[0])
5631 log_module(NS_LOG
, LOG_DEBUG
, "SASL: No mechanism stored yet, using %s", session
->buf
);
5632 if (strcmp(session
->buf
, "PLAIN")) {
5633 irc_sasl(session
->source
, session
->uid
, "M", "PLAIN");
5634 irc_sasl(session
->source
, session
->uid
, "D", "F");
5635 sasl_delete_session(session
);
5639 strncpy(session
->mech
, session
->buf
, 10);
5640 irc_sasl(session
->source
, session
->uid
, "C", "+");
5642 else /* We only have PLAIN at the moment so next message must be credentials */
5646 char *authzid
= NULL
;
5647 char *authcid
= NULL
;
5648 char *passwd
= NULL
;
5650 unsigned int i
= 0, c
= 0;
5651 struct handle_info
*hi
;
5653 base64_decode_alloc(session
->buf
, session
->buflen
, &raw
, &rawlen
);
5655 raw
= (char *)realloc(raw
, rawlen
+1);
5660 for (i
=0; i
<rawlen
; i
++)
5671 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Checking supplied credentials");
5675 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Incomplete credentials supplied");
5676 irc_sasl(session
->source
, session
->uid
, "D", "F");
5680 if (!(hi
= loc_auth(NULL
, authcid
, passwd
, NULL
)))
5682 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Invalid credentials supplied");
5683 irc_sasl(session
->source
, session
->uid
, "D", "F");
5687 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Valid credentials supplied");
5688 irc_sasl(session
->source
, session
->uid
, "L", hi
->handle
);
5689 irc_sasl(session
->source
, session
->uid
, "D", "S");
5693 sasl_delete_session(session
);
5699 /* clear stale state */
5700 session
->flags
&= ~SDFLAG_STALE
;
5704 handle_sasl_input(struct server
* source
,const char *uid
, const char *subcmd
, const char *data
, UNUSED_ARG(const char *ext
), UNUSED_ARG(void *extra
))
5706 struct SASLSession
* sess
= sasl_get_session(uid
);
5707 int len
= strlen(data
);
5709 sess
->source
= source
;
5711 if (!strcmp(subcmd
, "D"))
5713 sasl_delete_session(sess
);
5717 if (strcmp(subcmd
, "S") && strcmp(subcmd
, "C"))
5723 if (sess
->p
== NULL
)
5725 sess
->buf
= (char *)malloc(len
+ 1);
5726 sess
->p
= sess
->buf
;
5731 if (sess
->buflen
+ len
+ 1 > 8192) /* This is a little much... */
5733 irc_sasl(source
, uid
, "D", "F");
5734 sasl_delete_session(sess
);
5738 sess
->buf
= (char *)realloc(sess
->buf
, sess
->buflen
+ len
+ 1);
5739 sess
->p
= sess
->buf
+ sess
->buflen
;
5740 sess
->buflen
+= len
;
5743 memcpy(sess
->p
, data
, len
);
5745 /* Messages not exactly 400 bytes are the end of a packet. */
5751 sess
->buf
= sess
->p
= NULL
;
5756 nickserv_db_cleanup(UNUSED_ARG(void* extra
))
5758 unreg_del_user_func(nickserv_remove_user
, NULL
);
5759 unreg_sasl_input_func(handle_sasl_input
, NULL
);
5760 userList_clean(&curr_helpers
);
5761 policer_params_delete(nickserv_conf
.auth_policer_params
);
5762 dict_delete(nickserv_handle_dict
);
5763 dict_delete(nickserv_nick_dict
);
5764 dict_delete(nickserv_opt_dict
);
5765 dict_delete(nickserv_allow_auth_dict
);
5766 dict_delete(nickserv_email_dict
);
5767 dict_delete(nickserv_id_dict
);
5768 dict_delete(nickserv_conf
.weak_password_dict
);
5769 free(auth_func_list
);
5770 free(auth_func_list_extra
);
5771 free(unreg_func_list
);
5772 free(unreg_func_list_extra
);
5774 free(rf_list_extra
);
5775 free(allowauth_func_list
);
5776 free(allowauth_func_list_extra
);
5777 free(handle_merge_func_list
);
5778 free(handle_merge_func_list_extra
);
5779 free(failpw_func_list
);
5780 free(failpw_func_list_extra
);
5781 if (nickserv_conf
.valid_handle_regex_set
)
5782 regfree(&nickserv_conf
.valid_handle_regex
);
5783 if (nickserv_conf
.valid_nick_regex_set
)
5784 regfree(&nickserv_conf
.valid_nick_regex
);
5787 void handle_loc_auth_oper(struct userNode
*user
, UNUSED_ARG(struct handle_info
*old_handle
), UNUSED_ARG(void *extra
)) {
5788 char *privv
[MAXNUMPARAMS
];
5791 if (!*nickserv_conf
.auto_oper
|| !user
->handle_info
)
5794 if (!IsOper(user
)) {
5795 if (*nickserv_conf
.auto_admin
&& user
->handle_info
->opserv_level
>= opserv_conf_admin_level()) {
5796 if (nickserv_conf
.auto_admin_privs
[0]) {
5797 irc_raw_privs(user
, nickserv_conf
.auto_admin_privs
);
5798 privc
= split_line(strdup(nickserv_conf
.auto_admin_privs
), false, MAXNUMPARAMS
, privv
);
5799 for (i
= 0; i
< privc
; i
++) {
5800 client_modify_priv_by_name(user
, privv
[i
], 1);
5803 irc_umode(user
, nickserv_conf
.auto_admin
);
5804 irc_sno(0x1, "%s (%s@%s) is now an IRC Administrator",
5805 user
->nick
, user
->ident
, user
->hostname
);
5806 send_message(user
, nickserv
, "NSMSG_AUTO_OPER_ADMIN");
5807 } else if (*nickserv_conf
.auto_oper
&& user
->handle_info
->opserv_level
) {
5808 if (nickserv_conf
.auto_oper_privs
[0]) {
5809 irc_raw_privs(user
, nickserv_conf
.auto_oper_privs
);
5810 privc
= split_line(strdup(nickserv_conf
.auto_oper_privs
), false, MAXNUMPARAMS
, privv
);
5811 for (i
= 0; i
< privc
; i
++) {
5812 client_modify_priv_by_name(user
, privv
[i
], 1);
5815 irc_umode(user
, nickserv_conf
.auto_oper
);
5816 irc_sno(0x1, "%s (%s@%s) is now an IRC Operator",
5817 user
->nick
, user
->ident
, user
->hostname
);
5818 send_message(user
, nickserv
, "NSMSG_AUTO_OPER");
5824 init_nickserv(const char *nick
)
5826 struct chanNode
*chan
;
5828 NS_LOG
= log_register_type("NickServ", "file:nickserv.log");
5829 reg_new_user_func(check_user_nick
, NULL
);
5830 reg_nick_change_func(handle_nick_change
, NULL
);
5831 reg_del_user_func(nickserv_remove_user
, NULL
);
5832 reg_account_func(handle_account
);
5833 reg_auth_func(handle_loc_auth_oper
, NULL
);
5834 reg_sasl_input_func(handle_sasl_input
, NULL
);
5836 /* set up handle_inverse_flags */
5837 memset(handle_inverse_flags
, 0, sizeof(handle_inverse_flags
));
5838 for (i
=0; handle_flags
[i
]; i
++) {
5839 handle_inverse_flags
[(unsigned char)handle_flags
[i
]] = i
+ 1;
5840 flag_access_levels
[i
] = 0;
5843 conf_register_reload(nickserv_conf_read
);
5844 nickserv_opt_dict
= dict_new();
5845 nickserv_email_dict
= dict_new();
5847 dict_set_free_keys(nickserv_email_dict
, free
);
5848 dict_set_free_data(nickserv_email_dict
, nickserv_free_email_addr
);
5850 nickserv_module
= module_register("NickServ", NS_LOG
, "nickserv.help", NULL
);
5851 /* Removed qualified_host as default requirement for AUTH, REGISTER, PASS, etc. nets
5852 * can enable it per command using modcmd. (its a shitty default IMO, and now in 1.3
5853 * a big pain to disable since its nolonger in the config file. ) -Rubin
5855 modcmd_register(nickserv_module
, "AUTH", cmd_auth
, 2, MODCMD_KEEP_BOUND
, "flags", "+loghostmask", NULL
);
5856 nickserv_define_func("ALLOWAUTH", cmd_allowauth
, 0, 1, 0);
5857 nickserv_define_func("REGISTER", cmd_register
, -1, 0, 0);
5858 nickserv_define_func("OREGISTER", cmd_oregister
, 0, 1, 0);
5859 nickserv_define_func("UNREGISTER", cmd_unregister
, -1, 1, 0);
5860 nickserv_define_func("OUNREGISTER", cmd_ounregister
, 0, 1, 0);
5861 nickserv_define_func("ADDMASK", cmd_addmask
, -1, 1, 0);
5862 nickserv_define_func("OADDMASK", cmd_oaddmask
, 0, 1, 0);
5863 nickserv_define_func("DELMASK", cmd_delmask
, -1, 1, 0);
5864 nickserv_define_func("ODELMASK", cmd_odelmask
, 0, 1, 0);
5865 nickserv_define_func("ADDSSLFP", cmd_addsslfp
, -1, 1, 0);
5866 nickserv_define_func("OADDSSLFP", cmd_oaddsslfp
, 0, 1, 0);
5867 nickserv_define_func("DELSSLFP", cmd_delsslfp
, -1, 1, 0);
5868 nickserv_define_func("ODELSSLFP", cmd_odelsslfp
, 0, 1, 0);
5869 nickserv_define_func("PASS", cmd_pass
, -1, 1, 0);
5870 nickserv_define_func("SET", cmd_set
, -1, 1, 0);
5871 nickserv_define_func("OSET", cmd_oset
, 0, 1, 0);
5872 nickserv_define_func("ACCOUNTINFO", cmd_handleinfo
, -1, 0, 0);
5873 nickserv_define_func("USERINFO", cmd_userinfo
, -1, 1, 0);
5874 nickserv_define_func("RENAME", cmd_rename_handle
, -1, 1, 0);
5875 nickserv_define_func("VACATION", cmd_vacation
, -1, 1, 0);
5876 nickserv_define_func("MERGE", cmd_merge
, 750, 1, 0);
5877 if (!nickserv_conf
.disable_nicks
) {
5878 /* nick management commands */
5879 nickserv_define_func("REGNICK", cmd_regnick
, -1, 1, 0);
5880 nickserv_define_func("OREGNICK", cmd_oregnick
, 0, 1, 0);
5881 nickserv_define_func("UNREGNICK", cmd_unregnick
, -1, 1, 0);
5882 nickserv_define_func("OUNREGNICK", cmd_ounregnick
, 0, 1, 0);
5883 nickserv_define_func("NICKINFO", cmd_nickinfo
, -1, 1, 0);
5884 nickserv_define_func("RECLAIM", cmd_reclaim
, -1, 1, 0);
5886 if (nickserv_conf
.email_enabled
) {
5887 nickserv_define_func("AUTHCOOKIE", cmd_authcookie
, -1, 0, 0);
5888 nickserv_define_func("RESETPASS", cmd_resetpass
, -1, 0, 0);
5889 nickserv_define_func("COOKIE", cmd_cookie
, -1, 0, 0);
5890 nickserv_define_func("DELCOOKIE", cmd_delcookie
, -1, 1, 0);
5891 nickserv_define_func("ODELCOOKIE", cmd_odelcookie
, 0, 1, 0);
5892 dict_insert(nickserv_opt_dict
, "EMAIL", opt_email
);
5894 nickserv_define_func("GHOST", cmd_ghost
, -1, 1, 0);
5895 /* ignore commands */
5896 nickserv_define_func("ADDIGNORE", cmd_addignore
, -1, 1, 0);
5897 nickserv_define_func("OADDIGNORE", cmd_oaddignore
, 0, 1, 0);
5898 nickserv_define_func("DELIGNORE", cmd_delignore
, -1, 1, 0);
5899 nickserv_define_func("ODELIGNORE", cmd_odelignore
, 0, 1, 0);
5900 /* miscellaneous commands */
5901 nickserv_define_func("STATUS", cmd_status
, -1, 0, 0);
5902 nickserv_define_func("SEARCH", cmd_search
, 100, 1, 0);
5903 nickserv_define_func("SEARCH UNREGISTER", NULL
, 800, 1, 0);
5904 nickserv_define_func("MERGEDB", cmd_mergedb
, 999, 1, 0);
5905 nickserv_define_func("CHECKPASS", cmd_checkpass
, 601, 1, 0);
5906 nickserv_define_func("CHECKEMAIL", cmd_checkemail
, 0, 1, 0);
5908 dict_insert(nickserv_opt_dict
, "INFO", opt_info
);
5909 dict_insert(nickserv_opt_dict
, "WIDTH", opt_width
);
5910 dict_insert(nickserv_opt_dict
, "TABLEWIDTH", opt_tablewidth
);
5911 dict_insert(nickserv_opt_dict
, "COLOR", opt_color
);
5912 dict_insert(nickserv_opt_dict
, "PRIVMSG", opt_privmsg
);
5913 dict_insert(nickserv_opt_dict
, "AUTOHIDE", opt_autohide
);
5914 dict_insert(nickserv_opt_dict
, "STYLE", opt_style
);
5915 dict_insert(nickserv_opt_dict
, "PASS", opt_password
);
5916 dict_insert(nickserv_opt_dict
, "PASSWORD", opt_password
);
5917 dict_insert(nickserv_opt_dict
, "FLAGS", opt_flags
);
5918 dict_insert(nickserv_opt_dict
, "ACCESS", opt_level
);
5919 dict_insert(nickserv_opt_dict
, "LEVEL", opt_level
);
5920 dict_insert(nickserv_opt_dict
, "EPITHET", opt_epithet
);
5921 dict_insert(nickserv_opt_dict
, "NOTE", opt_note
);
5922 if (nickserv_conf
.titlehost_suffix
) {
5923 dict_insert(nickserv_opt_dict
, "TITLE", opt_title
);
5924 dict_insert(nickserv_opt_dict
, "FAKEHOST", opt_fakehost
);
5926 dict_insert(nickserv_opt_dict
, "ANNOUNCEMENTS", opt_announcements
);
5927 dict_insert(nickserv_opt_dict
, "MAXLOGINS", opt_maxlogins
);
5928 dict_insert(nickserv_opt_dict
, "ADVANCED", opt_advanced
);
5929 dict_insert(nickserv_opt_dict
, "LANGUAGE", opt_language
);
5930 dict_insert(nickserv_opt_dict
, "KARMA", opt_karma
);
5932 nickserv_handle_dict
= dict_new();
5933 dict_set_free_keys(nickserv_handle_dict
, free
);
5934 dict_set_free_data(nickserv_handle_dict
, free_handle_info
);
5936 nickserv_id_dict
= dict_new();
5937 dict_set_free_keys(nickserv_id_dict
, free
);
5939 nickserv_nick_dict
= dict_new();
5940 dict_set_free_data(nickserv_nick_dict
, free
);
5942 nickserv_allow_auth_dict
= dict_new();
5944 userList_init(&curr_helpers
);
5947 const char *modes
= conf_get_data("services/nickserv/modes", RECDB_QSTRING
);
5948 nickserv
= AddLocalUser(nick
, nick
, NULL
, "Nick Services", modes
);
5949 nickserv_service
= service_register(nickserv
);
5951 saxdb_register("NickServ", nickserv_saxdb_read
, nickserv_saxdb_write
);
5952 reg_exit_func(nickserv_db_cleanup
, NULL
);
5953 if(nickserv_conf
.handle_expire_frequency
)
5954 timeq_add(now
+ nickserv_conf
.handle_expire_frequency
, expire_handles
, NULL
);
5955 if(nickserv_conf
.nick_expire_frequency
&& nickserv_conf
.expire_nicks
)
5956 timeq_add(now
+ nickserv_conf
.nick_expire_frequency
, expire_nicks
, NULL
);
5958 if(autojoin_channels
&& nickserv
) {
5959 for (i
= 0; i
< autojoin_channels
->used
; i
++) {
5960 chan
= AddChannel(autojoin_channels
->list
[i
], now
, "+nt", NULL
, NULL
);
5961 AddChannelUser(nickserv
, chan
)->modes
|= MODE_CHANOP
;
5966 ldap_do_init(nickserv_conf
);
5969 message_register_table(msgtab
);