1 /* nickserv.c - Nick/authentication service
2 * Copyright 2000-2004 srvx Development Team
4 * This file is part of x3.
6 * x3 is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with srvx; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 #include "opserv.h" /* for gag_create(), opserv_bad_channel() */
33 #include <tre/regex.h>
39 #define NICKSERV_CONF_NAME "services/nickserv"
41 #define KEY_DISABLE_NICKS "disable_nicks"
42 #define KEY_DEFAULT_HOSTMASK "default_hostmask"
43 #define KEY_NICKS_PER_HANDLE "nicks_per_handle"
44 #define KEY_NICKS_PER_ACCOUNT "nicks_per_account"
45 #define KEY_PASSWORD_MIN_LENGTH "password_min_length"
46 #define KEY_PASSWORD_MIN_DIGITS "password_min_digits"
47 #define KEY_PASSWORD_MIN_UPPER "password_min_upper"
48 #define KEY_PASSWORD_MIN_LOWER "password_min_lower"
49 #define KEY_VALID_HANDLE_REGEX "valid_handle_regex"
50 #define KEY_VALID_ACCOUNT_REGEX "valid_account_regex"
51 #define KEY_VALID_NICK_REGEX "valid_nick_regex"
52 #define KEY_VALID_FAKEHOST_REGEX "valid_fakehost_regex"
53 #define KEY_DB_BACKUP_FREQ "db_backup_freq"
54 #define KEY_MODOPER_LEVEL "modoper_level"
55 #define KEY_SET_EPITHET_LEVEL "set_epithet_level"
56 #define KEY_SET_TITLE_LEVEL "set_title_level"
57 #define KEY_SET_FAKEHOST_LEVEL "set_fakehost_level"
58 #define KEY_DENIED_FAKEHOST_WORDS "denied_fakehost_words"
59 #define KEY_TITLEHOST_SUFFIX "titlehost_suffix"
60 #define KEY_AUTO_OPER "auto_oper"
61 #define KEY_AUTO_ADMIN "auto_admin"
62 #define KEY_AUTO_OPER_PRIVS "auto_oper_privs"
63 #define KEY_AUTO_ADMIN_PRIVS "auto_admin_privs"
64 #define KEY_FLAG_LEVELS "flag_levels"
65 #define KEY_HANDLE_EXPIRE_FREQ "handle_expire_freq"
66 #define KEY_ACCOUNT_EXPIRE_FREQ "account_expire_freq"
67 #define KEY_HANDLE_EXPIRE_DELAY "handle_expire_delay"
68 #define KEY_NICK_EXPIRE_FREQ "nick_expire_freq"
69 #define KEY_NICK_EXPIRE_DELAY "nick_expire_delay"
70 #define KEY_ACCOUNT_EXPIRE_DELAY "account_expire_delay"
71 #define KEY_NOCHAN_HANDLE_EXPIRE_DELAY "nochan_handle_expire_delay"
72 #define KEY_NOCHAN_ACCOUNT_EXPIRE_DELAY "nochan_account_expire_delay"
73 #define KEY_DICT_FILE "dict_file"
74 #define KEY_NICK "nick"
75 #define KEY_LANGUAGE "language"
76 #define KEY_AUTOGAG_ENABLED "autogag_enabled"
77 #define KEY_AUTOGAG_DURATION "autogag_duration"
78 #define KEY_AUTH_POLICER "auth_policer"
79 #define KEY_EMAIL_VISIBLE_LEVEL "email_visible_level"
80 #define KEY_EMAIL_ENABLED "email_enabled"
81 #define KEY_EMAIL_REQUIRED "email_required"
82 #define KEY_SYNC_LOG "sync_log"
83 #define KEY_COOKIE_TIMEOUT "cookie_timeout"
84 #define KEY_ACCOUNTS_PER_EMAIL "accounts_per_email"
85 #define KEY_EMAIL_SEARCH_LEVEL "email_search_level"
86 #define KEY_DEFAULT_STYLE "default_style"
87 #define KEY_OUNREGISTER_INACTIVE "ounregister_inactive"
88 #define KEY_OUNREGISTER_FLAGS "ounregister_flags"
91 #define KEY_PASSWD "passwd"
92 #define KEY_NICKS "nicks"
93 #define KEY_NICKS_EX "nicks_ex"
94 #define KEY_MASKS "masks"
95 #define KEY_SSLFPS "sslfps"
96 #define KEY_IGNORES "ignores"
97 #define KEY_OPSERV_LEVEL "opserv_level"
98 #define KEY_FLAGS "flags"
99 #define KEY_REGISTER_ON "register"
100 #define KEY_LAST_SEEN "lastseen"
101 #define KEY_INFO "info"
102 #define KEY_USERLIST_STYLE "user_style"
103 #define KEY_SCREEN_WIDTH "screen_width"
104 #define KEY_LAST_AUTHED_HOST "last_authed_host"
105 #define KEY_LAST_QUIT_HOST "last_quit_host"
106 #define KEY_EMAIL_ADDR "email_addr"
107 #define KEY_COOKIE "cookie"
108 #define KEY_COOKIE_DATA "data"
109 #define KEY_COOKIE_TYPE "type"
110 #define KEY_COOKIE_EXPIRES "expires"
111 #define KEY_ACTIVATION "activation"
112 #define KEY_PASSWORD_CHANGE "password change"
113 #define KEY_EMAIL_CHANGE "email change"
114 #define KEY_ALLOWAUTH "allowauth"
115 #define KEY_EPITHET "epithet"
116 #define KEY_TABLE_WIDTH "table_width"
117 #define KEY_ANNOUNCEMENTS "announcements"
118 #define KEY_MAXLOGINS "maxlogins"
119 #define KEY_FAKEHOST "fakehost"
120 #define KEY_NOTE_NOTE "note"
121 #define KEY_NOTE_SETTER "setter"
122 #define KEY_NOTE_DATE "date"
123 #define KEY_KARMA "karma"
124 #define KEY_FORCE_HANDLES_LOWERCASE "force_handles_lowercase"
126 #define KEY_LDAP_ENABLE "ldap_enable"
129 #define KEY_LDAP_URI "ldap_uri"
130 #define KEY_LDAP_BASE "ldap_base"
131 #define KEY_LDAP_DN_FMT "ldap_dn_fmt"
132 #define KEY_LDAP_VERSION "ldap_version"
133 #define KEY_LDAP_AUTOCREATE "ldap_autocreate"
134 #define KEY_LDAP_ADMIN_DN "ldap_admin_dn"
135 #define KEY_LDAP_ADMIN_PASS "ldap_admin_pass"
136 #define KEY_LDAP_FIELD_ACCOUNT "ldap_field_account"
137 #define KEY_LDAP_FIELD_PASSWORD "ldap_field_password"
138 #define KEY_LDAP_FIELD_EMAIL "ldap_field_email"
139 #define KEY_LDAP_FIELD_OSLEVEL "ldap_field_oslevel"
140 #define KEY_LDAP_OBJECT_CLASSES "ldap_object_classes"
141 #define KEY_LDAP_OPER_GROUP_DN "ldap_oper_group_dn"
142 #define KEY_LDAP_OPER_GROUP_LEVEL "ldap_oper_group_level"
143 #define KEY_LDAP_FIELD_GROUP_MEMBER "ldap_field_group_member"
144 #define KEY_LDAP_TIMEOUT "ldap_timeout"
147 #define NICKSERV_VALID_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
149 #define NICKSERV_FUNC(NAME) MODCMD_FUNC(NAME)
150 #define OPTION_FUNC(NAME) int NAME(UNUSED_ARG(struct svccmd *cmd), struct userNode *user, struct handle_info *hi, UNUSED_ARG(unsigned int override), int noreply, unsigned int argc, char *argv[])
151 typedef OPTION_FUNC(option_func_t
);
153 DEFINE_LIST(handle_info_list
, struct handle_info
*)
155 #define NICKSERV_MIN_PARMS(N) do { \
157 reply("MSG_MISSING_PARAMS", argv[0]); \
158 svccmd_send_help_brief(user, nickserv, cmd); \
162 struct userNode
*nickserv
;
163 struct userList curr_helpers
;
164 const char *handle_flags
= HANDLE_FLAGS
;
166 extern struct string_list
*autojoin_channels
;
167 static struct module *nickserv_module
;
168 static struct service
*nickserv_service
;
169 static struct log_type
*NS_LOG
;
170 dict_t nickserv_handle_dict
; /* contains struct handle_info* */
171 static dict_t nickserv_id_dict
; /* contains struct handle_info* */
172 static dict_t nickserv_nick_dict
; /* contains struct nick_info* */
173 static dict_t nickserv_opt_dict
; /* contains option_func_t* */
174 static dict_t nickserv_allow_auth_dict
; /* contains struct handle_info* */
175 static dict_t nickserv_email_dict
; /* contains struct handle_info_list*, indexed by email addr */
176 static char handle_inverse_flags
[256];
177 static unsigned int flag_access_levels
[32];
178 static const struct message_entry msgtab
[] = {
179 { "NSMSG_NO_ANGLEBRACKETS", "The < and > in help indicate that that word is a required parameter, but DO NOT actually type them in messages to me." },
180 { "NSMSG_HANDLE_EXISTS", "Account $b%s$b is already registered." },
181 { "NSMSG_HANDLE_TOLONG", "The account name %s is too long. Account names must be %lu characters or less."},
182 { "NSMSG_PASSWORD_SHORT", "Your password must be at least %lu characters long." },
183 { "NSMSG_PASSWORD_ACCOUNT", "Your password may not be the same as your account name." },
184 { "NSMSG_PASSWORD_DICTIONARY", "Your password is too simple. You must choose a password that is not just a word or name." },
185 { "NSMSG_PASSWORD_READABLE", "Your password must have at least %lu digit(s), %lu capital letter(s), and %lu lower-case letter(s)." },
186 { "NSMSG_LDAP_FAIL", "There was a problem in contacting the account server (ldap): %s. Please try again later." },
187 { "NSMSG_LDAP_FAIL_ADD", "There was a problem in adding account %s to ldap: %s." },
188 { "NSMSG_LDAP_FAIL_SEND_EMAIL", "There was a problem in storing your email address in the account server (ldap): %s. Please try again later." },
189 { "NSMSG_LDAP_FAIL_GET_EMAIL", "There was a problem in retrieving your email address from the account server (ldap): %s. Please try again later." },
190 { "NSMSG_PARTIAL_REGISTER", "Account has been registered to you; nick was already registered to someone else." },
191 { "NSMSG_OREGISTER_VICTIM", "%s has registered a new account for you (named %s)." },
192 { "NSMSG_OREGISTER_H_SUCCESS", "Account has been registered." },
193 { "NSMSG_REGISTER_H_SUCCESS", "Account has been registered to you." },
194 { "NSMSG_REGISTER_HN_SUCCESS", "Account and nick have been registered to you." },
195 { "NSMSG_REQUIRE_OPER", "You must be an $bIRC Operator$b to register the first account." },
196 { "NSMSG_ROOT_HANDLE", "Account %s has been granted $broot-level privileges$b." },
197 { "NSMSG_USE_COOKIE_REGISTER", "To activate your account, you must check your email for the \"cookie\" that has been mailed to it. When you have it, use the $bcookie$b command to complete registration." },
198 { "NSMSG_USE_COOKIE_RESETPASS", "A cookie has been mailed to your account's email address. You must check your email and use the $bcookie$b command to confirm the password change." },
199 { "NSMSG_USE_COOKIE_EMAIL_1", "A cookie has been mailed to the new address you requested. To finish setting your email address, please check your email for the cookie and use the $bcookie$b command to verify." },
200 { "NSMSG_USE_COOKIE_EMAIL_2", "A cookie has been generated, and half mailed to each your old and new addresses. To finish changing your email address, please check your email for the cookie and use the $bcookie$b command to verify." },
201 { "NSMSG_USE_COOKIE_AUTH", "A cookie has been generated and sent to your email address. Once you have checked your email and received the cookie, auth using the $bcookie$b command." },
202 { "NSMSG_COOKIE_LIVE", "Account $b%s$b already has a cookie active. Please either finish using that cookie, wait for it to expire, or auth to the account and use the $bdelcookie$b command." },
203 { "NSMSG_EMAIL_UNACTIVATED", "That email address already has an unused cookie outstanding. Please use the cookie or wait for it to expire." },
204 { "NSMSG_NO_COOKIE", "Your account does not have any cookie issued right now." },
205 { "NSMSG_NO_COOKIE_FOREIGN", "The account $b%s$b does not have any cookie issued right now." },
206 { "NSMSG_CANNOT_COOKIE", "You cannot use that kind of cookie when you are logged in." },
207 { "NSMSG_BAD_COOKIE", "That cookie is not the right one. Please make sure you are copying it EXACTLY from the email; it is case-sensitive, so $bABC$b is different from $babc$b." },
208 { "NSMSG_HANDLE_ACTIVATED", "Your account is now activated (with the password you entered when you registered). You are now authenticated to your account." },
209 { "NSMSG_PASSWORD_CHANGED", "You have successfully changed your password to what you requested with the $bresetpass$b command." },
210 { "NSMSG_EMAIL_PROHIBITED", "%s may not be used as an email address: %s" },
211 { "NSMSG_EMAIL_OVERUSED", "That email address already has an account. Use RESETPASS if you forgot your password." },
212 { "NSMSG_EMAIL_SAME", "That is the email address already there; no need to change it." },
213 { "NSMSG_EMAIL_CHANGED", "You have successfully changed your email address." },
214 { "NSMSG_BAD_COOKIE_TYPE", "Your account had bad cookie type %d; sorry. I am confused. Please report this bug." },
215 { "NSMSG_MUST_TIME_OUT", "You must wait for cookies of that type to time out." },
216 { "NSMSG_ATE_COOKIE", "I ate the cookie for your account. You may now have another." },
217 { "NSMSG_ATE_FOREIGN_COOKIE", "I ate the cookie for account $b%s$b. It may now have another." },
218 { "NSMSG_USE_RENAME", "You are already authenticated to account $b%s$b -- contact the support staff to rename your account." },
219 { "NSMSG_ALREADY_REGISTERING", "You have already used $bREGISTER$b once this session; you may not use it again." },
220 { "NSMSG_REGISTER_BAD_NICKMASK", "You must provide a hostmask, or online nick to generate one automatically. (or set a default hostmask in the config such as *@*)." },
221 { "NSMSG_NICK_NOT_REGISTERED", "Nick $b%s$b has not been registered to any account." },
222 { "NSMSG_HANDLE_NOT_FOUND", "Could not find your account -- did you register yet?" },
223 { "NSMSG_ALREADY_AUTHED", "You are already authed to account $b%s$b; you must reconnect to auth to a different account." },
224 { "NSMSG_USE_AUTHCOOKIE", "Your hostmask is not valid for account $b%1$s$b. Please use the $bauthcookie$b command to grant yourself access. (/msg $N authcookie %1$s)" },
225 { "NSMSG_HOSTMASK_INVALID", "Your hostmask is not valid for account $b%s$b." },
226 { "NSMSG_USER_IS_SERVICE", "$b%s$b is a network service; you can only use that command on real users." },
227 { "NSMSG_USER_PREV_AUTH", "$b%s$b is already authenticated." },
228 { "NSMSG_USER_PREV_STAMP", "$b%s$b has authenticated to an account once and cannot authenticate again." },
229 { "NSMSG_BAD_MAX_LOGINS", "MaxLogins must be at most %d." },
230 { "NSMSG_BAD_ADVANCED", "Advanced must be either 1 to enable it or 0 to disable it." },
231 { "NSMSG_LANGUAGE_NOT_FOUND", "Language $b%s$b is not supported; $b%s$b was the closest available match." },
232 { "NSMSG_MAX_LOGINS", "Your account already has its limit of %d user(s) logged in." },
233 { "NSMSG_STAMPED_REGISTER", "You have already authenticated to an account once this session; you may not register a new account." },
234 { "NSMSG_STAMPED_AUTH", "You have already authenticated to an account once this session; you may not authenticate to another." },
235 { "NSMSG_STAMPED_RESETPASS", "You have already authenticated to an account once this session; you may not reset your password to authenticate again." },
236 { "NSMSG_STAMPED_AUTHCOOKIE", "You have already authenticated to an account once this session; you may not use a cookie to authenticate to another account." },
237 { "NSMSG_TITLE_INVALID", "Titles may contain only a-z, A-Z, 0-9, and '-'. Please choose another." },
238 { "NSMSG_TITLE_TRUNCATED", "That title combined with the user's account name would result in a truncated host; please choose a shorter title." },
239 { "NSMSG_FAKEHOST_INVALID", "Fake hosts must be shorter than %d characters and cannot start with a dot." },
240 { "NSMSG_HANDLEINFO_ON", "$bAccount Information for %s$b" },
241 { "NSMSG_HANDLEINFO_END", "----------End of Account Info-----------" },
242 { "NSMSG_HANDLEINFO_ID", "Account ID: %lu" },
243 { "NSMSG_HANDLEINFO_REGGED", "Registered on: %s" },
244 { "NSMSG_HANDLEINFO_LASTSEEN", "Last seen: %s" },
245 { "NSMSG_HANDLEINFO_LASTSEEN_NOW", "Last seen: Right now!" },
246 { "NSMSG_HANDLEINFO_KARMA", "Karma: %d" },
247 { "NSMSG_HANDLEINFO_VACATION", "On vacation." },
248 { "NSMSG_HANDLEINFO_EMAIL_ADDR", "Email address: %s" },
249 { "NSMSG_HANDLEINFO_COOKIE_ACTIVATION", "Cookie: There is currently an activation cookie issued for this account" },
250 { "NSMSG_HANDLEINFO_COOKIE_PASSWORD", "Cookie: There is currently a password change cookie issued for this account" },
251 { "NSMSG_HANDLEINFO_COOKIE_EMAIL", "Cookie: There is currently an email change cookie issued for this account" },
252 { "NSMSG_HANDLEINFO_COOKIE_ALLOWAUTH", "Cookie: There is currently an allowauth cookie issued for this account" },
253 { "NSMSG_HANDLEINFO_COOKIE_UNKNOWN", "Cookie: There is currently an unknown cookie issued for this account" },
254 { "NSMSG_HANDLEINFO_COOKIE_EMAIL_DATA", "Cookie: New email address: %s" },
255 { "NSMSG_HANDLEINFO_INFOLINE", "Infoline: %s" },
256 { "NSMSG_HANDLEINFO_FLAGS", "Flags: %s" },
257 { "NSMSG_HANDLEINFO_OPSERV_LEVEL", "Opserv level: %d " },
258 { "NSMSG_HANDLEINFO_EPITHET", "Epithet: %s" },
259 { "NSMSG_HANDLEINFO_NOTE", "Note (by %s on %s): %s " },
260 { "NSMSG_HANDLEINFO_FAKEHOST", "Fake host: %s" },
261 { "NSMSG_INVALID_KARMA", "$b%s$b is not a valid karma modifier." },
262 { "NSMSG_SET_KARMA", "$bKARMA: $b%d$b" },
263 { "NSMSG_HANDLEINFO_LAST_HOST", "Last quit hostmask: %s" },
264 { "NSMSG_HANDLEINFO_LAST_HOST_UNKNOWN", "Last quit hostmask: Unknown" },
265 { "NSMSG_HANDLEINFO_NICKS", "Nickname(s): %s" },
266 { "NSMSG_HANDLEINFO_MASKS", "Hostmask(s): %s" },
267 { "NSMSG_HANDLEINFO_SSLFPS", "SSL Fingerprints(s): %s" },
268 { "NSMSG_HANDLEINFO_IGNORES", "Ignore(s): %s" },
269 { "NSMSG_HANDLEINFO_CHANNELS", "Channel(s): %s" },
270 { "NSMSG_HANDLEINFO_CURRENT", "Current nickname(s): %s" },
271 { "NSMSG_HANDLEINFO_DNR", "Do-not-register (by %s): %s" },
272 { "NSMSG_USERINFO_AUTHED_AS", "$b%s$b is authenticated to account $b%s$b." },
273 { "NSMSG_USERINFO_NOT_AUTHED", "$b%s$b is not authenticated to any account." },
274 { "NSMSG_NICKINFO_ON", "$bNick Information for %s$b" },
275 { "NSMSG_NICKINFO_END", "----------End of Nick Info-----------" },
276 { "NSMSG_NICKINFO_REGGED", "Registered on: %s" },
277 { "NSMSG_NICKINFO_LASTSEEN", "Last seen: %s" },
278 { "NSMSG_NICKINFO_LASTSEEN_NOW", "Last seen: Right now!" },
279 { "NSMSG_NICKINFO_OWNER", "Account: %s." },
280 { "NSMSG_PASSWORD_INVALID", "Incorrect password; please try again." },
281 { "NSMSG_PLEASE_SET_EMAIL", "We now require email addresses for users. Please use the $bset email$b command to set your email address!" },
282 { "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)." },
283 { "NSMSG_HANDLE_SUSPENDED", "Your $b$N$b account has been suspended; you may not use it." },
284 { "NSMSG_AUTH_SUCCESS", "I recognize you." },
285 { "NSMSG_ALLOWAUTH_STAFF", "$b%s$b is a helper or oper; please use $bstaff$b after the account name to allowauth." },
286 { "NSMSG_AUTH_ALLOWED", "User $b%s$b may now authenticate to account $b%s$b." },
287 { "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." },
288 { "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." },
289 { "NSMSG_AUTH_NORMAL_ONLY", "User $b%s$b may now only authenticate to accounts with matching hostmasks." },
290 { "NSMSG_AUTH_UNSPECIAL", "User $b%s$b did not have any special auth allowance." },
291 { "NSMSG_MUST_AUTH", "You must be authenticated first." },
292 { "NSMSG_TOO_MANY_NICKS", "You have already registered the maximum permitted number of nicks." },
293 { "NSMSG_NICK_EXISTS", "Nick $b%s$b already registered." },
294 { "NSMSG_REGNICK_SUCCESS", "Nick $b%s$b has been registered to you." },
295 { "NSMSG_OREGNICK_SUCCESS", "Nick $b%s$b has been registered to account $b%s$b." },
296 { "NSMSG_PASS_SUCCESS", "Password changed." },
297 { "NSMSG_MASK_INVALID", "$b%s$b is an invalid hostmask." },
298 { "NSMSG_ADDMASK_ALREADY", "$b%s$b is already a hostmask in your account." },
299 { "NSMSG_ADDMASK_SUCCESS", "Hostmask %s added." },
300 { "NSMSG_ADDIGNORE_ALREADY", "$b%s$b is already an ignored hostmask in your account." },
301 { "NSMSG_ADDIGNORE_SUCCESS", "Hostmask %s added." },
302 { "NSMSG_ADDSSLFP_ALREADY", "$b%s$b is already an SSL fingerprint in your account." },
303 { "NSMSG_ADDSSLFP_SUCCESS", "SSL fingerprint %s added." },
304 { "NSMSG_DELMASK_NOTLAST", "You may not delete your last hostmask." },
305 { "NSMSG_DELMASK_SUCCESS", "Hostmask %s deleted." },
306 { "NSMSG_DELMASK_NOT_FOUND", "Unable to find mask to be deleted." },
307 { "NSMSG_DELSSLFP_SUCCESS", "SSL fingerprint %s deleted." },
308 { "NSMSG_DELSSLFP_NOT_FOUND", "Unable to find SSL fingerprint to be deleted." },
309 { "NSMSG_OPSERV_LEVEL_BAD", "You may not promote another oper above your level." },
310 { "NSMSG_USE_CMD_PASS", "Please use the PASS command to change your password." },
311 { "NSMSG_UNKNOWN_NICK", "I know nothing about nick $b%s$b." },
312 { "NSMSG_NOT_YOUR_NICK", "The nick $b%s$b is not registered to you." },
313 { "NSMSG_NICK_USER_YOU", "I will not let you kill yourself." },
314 { "NSMSG_UNREGNICK_SUCCESS", "Nick $b%s$b has been unregistered." },
315 { "NSMSG_UNREGISTER_SUCCESS", "Account $b%s$b has been unregistered." },
316 { "NSMSG_UNREGISTER_NICKS_SUCCESS", "Account $b%s$b and all its nicks have been unregistered." },
317 { "NSMSG_UNREGISTER_MUST_FORCE", "Account $b%s$b is not inactive or has special flags set; use FORCE to unregister it." },
318 { "NSMSG_UNREGISTER_CANNOT_FORCE", "Account $b%s$b is not inactive or has special flags set; have an IRCOp use FORCE to unregister it." },
319 { "NSMSG_UNREGISTER_NODELETE", "Account $b%s$b is protected from unregistration." },
320 { "NSMSG_HANDLE_STATS", "There are %d nicks registered to your account." },
321 { "NSMSG_HANDLE_NONE", "You are not authenticated against any account." },
322 { "NSMSG_GLOBAL_STATS", "There are %d accounts and %d nicks registered globally." },
323 { "NSMSG_GLOBAL_STATS_NONICK", "There are %d accounts registered." },
324 { "NSMSG_CANNOT_GHOST_SELF", "You may not ghost-kill yourself." },
325 { "NSMSG_CANNOT_GHOST_USER", "$b%s$b is not authed to your account; you may not ghost-kill them." },
326 { "NSMSG_GHOST_KILLED", "$b%s$b has been killed as a ghost." },
327 { "NSMSG_ON_VACATION", "You are now on vacation. Your account will be preserved until you authenticate again." },
328 { "NSMSG_NO_ACCESS", "Access denied." },
329 { "NSMSG_INVALID_FLAG", "$b%c$b is not a valid $N account flag." },
330 { "NSMSG_SET_FLAG", "Applied flags $b%s$b to %s's $N account." },
331 { "NSMSG_FLAG_PRIVILEGED", "You have insufficient access to set flag %c." },
332 { "NSMSG_DB_UNREADABLE", "Unable to read database file %s; check the log for more information." },
333 { "NSMSG_DB_MERGED", "$N merged DB from %s (in "FMT_TIME_T
".%03lu seconds)." },
334 { "NSMSG_HANDLE_CHANGED", "$b%s$b's account name has been changed to $b%s$b." },
335 { "NSMSG_BAD_HANDLE", "Account $b%s$b is not allowed because it is reserved, is too long, or contains invalid characters." },
336 { "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." },
337 { "NSMSG_BAD_EMAIL_ADDR", "Please use a well-formed email address." },
338 { "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." },
339 { "NSMSG_ACCOUNT_SEARCH_RESULTS", "The following accounts were found:" },
340 { "NSMSG_SEARCH_MATCH", "Match: %s" },
341 { "NSMSG_INVALID_ACTION", "%s is an invalid search action." },
342 { "NSMSG_CANNOT_MERGE_SELF", "You cannot merge account $b%s$b with itself." },
343 { "NSMSG_HANDLES_MERGED", "Merged account $b%s$b into $b%s$b." },
344 { "NSMSG_RECLAIM_WARN", "%s is a registered nick - you must auth to account %s or change your nick." },
345 { "NSMSG_RECLAIM_HOWTO", "To auth to account %s you must use /msg %s@%s AUTH %s <password>" },
346 { "NSMSG_RECLAIM_KILL", "Unauthenticated user of nick." },
347 { "NSMSG_RECLAIMED_NONE", "You cannot manually reclaim a nick." },
348 { "NSMSG_RECLAIMED_WARN", "Sent a request for %s to change their nick." },
349 { "NSMSG_RECLAIMED_SVSNICK", "Forcibly changed %s's nick." },
350 { "NSMSG_RECLAIMED_KILL", "Disconnected %s from the network." },
351 { "NSMSG_CLONE_AUTH", "Warning: %s (%s@%s) authed to your account." },
352 { "NSMSG_SETTING_LIST", "$b$N account settings$b" },
353 { "NSMSG_SETTING_LIST_HEADER", "----------------------------------------" },
354 { "NSMSG_SETTING_LIST_END", "-------------End Of Settings------------" },
355 { "NSMSG_INVALID_OPTION", "$b%s$b is an invalid account setting." },
356 { "NSMSG_INVALID_ANNOUNCE", "$b%s$b is an invalid announcements value." },
357 { "NSMSG_SET_INFO", "$bINFO: $b%s" },
358 { "NSMSG_SET_WIDTH", "$bWIDTH: $b%d" },
359 { "NSMSG_SET_TABLEWIDTH", "$bTABLEWIDTH: $b%d" },
360 { "NSMSG_SET_COLOR", "$bCOLOR: $b%s" },
361 { "NSMSG_SET_PRIVMSG", "$bPRIVMSG: $b%s" },
362 { "NSMSG_SET_STYLE", "$bSTYLE: $b%s" },
363 { "NSMSG_SET_ANNOUNCEMENTS", "$bANNOUNCEMENTS: $b%s" },
364 { "NSMSG_SET_AUTOHIDE", "$bAUTOHIDE: $b%s" },
365 { "NSMSG_SET_PASSWORD", "$bPASSWORD: $b%s" },
366 { "NSMSG_SET_FLAGS", "$bFLAGS: $b%s" },
367 { "NSMSG_SET_EMAIL", "$bEMAIL: $b%s" },
368 { "NSMSG_SET_MAXLOGINS", "$bMAXLOGINS: $b%d" },
369 { "NSMSG_SET_ADVANCED", "$bADVANCED: $b%s" },
370 { "NSMSG_SET_LANGUAGE", "$bLANGUAGE: $b%s" },
371 { "NSMSG_SET_LEVEL", "$bLEVEL: $b%d" },
372 { "NSMSG_SET_EPITHET", "$bEPITHET: $b%s" },
373 { "NSMSG_SET_NOTE", "$bNOTE: $b%s"},
374 { "NSMSG_SET_TITLE", "$bTITLE: $b%s" },
375 { "NSMSG_SET_FAKEHOST", "$bFAKEHOST: $b%s" },
377 { "NSMSG_AUTO_OPER", "You have been auto-opered" },
378 { "NSMSG_AUTO_OPER_ADMIN", "You have been auto-admined" },
380 { "NSEMAIL_ACTIVATION_SUBJECT", "Account verification for %s" },
381 { "NSEMAIL_ACTIVATION_BODY",
382 "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"
384 "To verify your email address and complete the account registration, log on to %1$s and type the following command:\n"
385 "/msg %3$s@%4$s COOKIE %5$s %2$s\n"
386 "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"
387 "/msg %3$s@%4$s AUTH %5$s your-password\n"
388 "(Please remember to fill in 'your-password' with the actual password you gave to us when you registered.)\n"
389 "OR configure Login-On-Connect (see http://www.afternet.org/login-on-connect for instructions) to connect pre-logged in every time.\n"
391 "If you did NOT request this account, you do not need to do anything.\n"
392 "Please contact the %1$s staff if you have questions, and be sure to check our website." },
393 { "NSEMAIL_ACTIVATION_BODY_WEB",
394 "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"
396 "To verify your email address and complete the account registration, visit the following URL:\n"
397 "http://www.afternet.org/index.php?option=com_registration&task=activate&username=%5$s&cookie=%2$s\n"
399 "If you did NOT request this account, you do not need to do anything.\n"
400 "Please contact the %1$s staff if you have questions, and be sure to check our website." },
401 { "NSEMAIL_PASSWORD_CHANGE_SUBJECT", "Password change verification on %s" },
402 { "NSEMAIL_PASSWORD_CHANGE_BODY",
403 "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"
404 "To complete the password change, log on to %1$s and type the following command:\n"
405 "/msg %3$s@%4$s COOKIE %5$s %2$s\n"
406 "If you did NOT request your password to be changed, you do not need to do anything.\n"
407 "Please contact the %1$s staff if you have questions." },
408 { "NSEMAIL_PASSWORD_CHANGE_BODY_WEB",
409 "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"
410 "To complete the password change, click the following URL:\n"
411 "http://www.afternet.org/index.php?option=com_registration&task=passcookie&username=%5$s&cookie=%2$s\n"
412 "If you did NOT request your password to be changed, you do not need to do anything.\n"
413 "Please contact the %1$s staff if you have questions." },
414 { "NSEMAIL_EMAIL_CHANGE_SUBJECT", "Email address change verification for %s" },
415 #ifdef stupid_verify_old_email
416 { "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." },
417 { "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." },
419 { "NSEMAIL_EMAIL_VERIFY_SUBJECT", "Email address verification for %s" },
420 { "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." },
421 { "NSEMAIL_ALLOWAUTH_SUBJECT", "Authentication allowed for %s" },
422 { "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." },
423 { "NSMSG_NOT_VALID_FAKEHOST_DOT", "$b%s$b is not a valid vhost. (needs at least one dot)" },
424 { "NSMSG_NOT_VALID_FAKEHOST_AT", "$b%s$b is not a valid vhost. (it can not have a '@')" },
425 { "NSMSG_DENIED_FAKEHOST_WORD", "Access denied because there's a prohibited word in $b%s$b (%s)." },
426 { "NSMSG_NOT_VALID_FAKEHOST_LEN", "$b%s$b is not a valid vhost. (can only be 63 characters)" },
427 { "NSMSG_NOT_VALID_FAKEHOST_TLD_LEN", "$b%s$b is not a valid vhost. (TLD can only be 4 characters and less)" },
428 { "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." },
429 { "CHECKPASS_YES", "Yes." },
430 { "CHECKPASS_NO", "No." },
431 { "CHECKEMAIL_NOT_SET", "No email set." },
432 { "CHECKEMAIL_YES", "Yes." },
433 { "CHECKEMAIL_NO", "No." },
434 { "NSMSG_DEFCON_NO_NEW_NICKS", "You cannot register new %s at this time, please try again soon" },
438 static void nickserv_reclaim(struct userNode
*user
, struct nick_info
*ni
, enum reclaim_action action
);
439 static void nickserv_reclaim_p(void *data
);
440 static int nickserv_addmask(struct userNode
*user
, struct handle_info
*hi
, const char *mask
);
442 struct nickserv_config nickserv_conf
;
444 /* We have 2^32 unique account IDs to use. */
445 unsigned long int highest_id
= 0;
448 canonicalize_hostmask(char *mask
)
450 char *out
= mask
, *temp
;
451 if ((temp
= strchr(mask
, '!'))) {
453 while (*temp
) *out
++ = *temp
++;
459 static struct handle_note
*
460 nickserv_add_note(const char *setter
, time_t date
, const char *text
)
462 struct handle_note
*note
= calloc(1, sizeof(*note
) + strlen(text
));
464 strncpy(note
->setter
, setter
, sizeof(note
->setter
)-1);
466 memcpy(note
->note
, text
, strlen(text
));
470 static struct handle_info
*
471 register_handle(const char *handle
, const char *passwd
, UNUSED_ARG(unsigned long id
))
473 struct handle_info
*hi
;
475 hi
= calloc(1, sizeof(*hi
));
476 hi
->userlist_style
= nickserv_conf
.default_style
? nickserv_conf
.default_style
: HI_DEFAULT_STYLE
;
477 hi
->announcements
= '?';
478 hi
->handle
= strdup(handle
);
479 safestrncpy(hi
->passwd
, passwd
, sizeof(hi
->passwd
));
481 dict_insert(nickserv_handle_dict
, hi
->handle
, hi
);
487 register_nick(const char *nick
, struct handle_info
*owner
)
489 struct nick_info
*ni
;
490 ni
= malloc(sizeof(struct nick_info
));
491 safestrncpy(ni
->nick
, nick
, sizeof(ni
->nick
));
492 ni
->registered
= now
;
495 ni
->next
= owner
->nicks
;
497 dict_insert(nickserv_nick_dict
, ni
->nick
, ni
);
501 delete_nick(struct nick_info
*ni
)
503 struct nick_info
*last
, *next
;
504 struct userNode
*user
;
505 /* Check to see if we should mark a user as unregistered. */
506 if ((user
= GetUserH(ni
->nick
)) && IsReggedNick(user
)) {
507 user
->modes
&= ~FLAGS_REGNICK
;
510 /* Remove ni from the nick_info linked list. */
511 if (ni
== ni
->owner
->nicks
) {
512 ni
->owner
->nicks
= ni
->next
;
514 last
= ni
->owner
->nicks
;
520 last
->next
= next
->next
;
522 dict_remove(nickserv_nick_dict
, ni
->nick
);
525 static unreg_func_t
*unreg_func_list
;
526 static void **unreg_func_list_extra
;
527 static unsigned int unreg_func_size
= 0, unreg_func_used
= 0;
530 reg_unreg_func(unreg_func_t func
, void *extra
)
532 if (unreg_func_used
== unreg_func_size
) {
533 if (unreg_func_size
) {
534 unreg_func_size
<<= 1;
535 unreg_func_list
= realloc(unreg_func_list
, unreg_func_size
*sizeof(unreg_func_t
));
536 unreg_func_list_extra
= realloc(unreg_func_list_extra
, unreg_func_size
*sizeof(void*));
539 unreg_func_list
= malloc(unreg_func_size
*sizeof(unreg_func_t
));
540 unreg_func_list_extra
= malloc(unreg_func_size
*sizeof(void*));
543 unreg_func_list
[unreg_func_used
] = func
;
544 unreg_func_list_extra
[unreg_func_used
++] = extra
;
548 nickserv_free_cookie(void *data
)
550 struct handle_cookie
*cookie
= data
;
551 if (cookie
->hi
) cookie
->hi
->cookie
= NULL
;
552 if (cookie
->data
) free(cookie
->data
);
557 free_handle_info(void *vhi
)
559 struct handle_info
*hi
= vhi
;
561 free_string_list(hi
->masks
);
562 free_string_list(hi
->sslfps
);
563 free_string_list(hi
->ignores
);
567 delete_nick(hi
->nicks
);
573 timeq_del(hi
->cookie
->expires
, nickserv_free_cookie
, hi
->cookie
, 0);
574 nickserv_free_cookie(hi
->cookie
);
576 if (hi
->email_addr
) {
577 struct handle_info_list
*hil
= dict_find(nickserv_email_dict
, hi
->email_addr
, NULL
);
578 handle_info_list_remove(hil
, hi
);
580 dict_remove(nickserv_email_dict
, hi
->email_addr
);
585 static void set_user_handle_info(struct userNode
*user
, struct handle_info
*hi
, int stamp
);
588 nickserv_unregister_handle(struct handle_info
*hi
, struct userNode
*notify
, struct userNode
*bot
)
591 struct userNode
*uNode
;
594 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
596 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
597 if( (rc
= ldap_delete_account(hi
->handle
)) != LDAP_SUCCESS
) {
599 send_message(notify
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
601 if(rc
!= LDAP_NO_SUCH_OBJECT
)
602 return false; /* if theres noone there to delete, its kinda ok, right ?:) */
607 for (n
=0; n
<unreg_func_used
; n
++)
608 unreg_func_list
[n
](notify
, hi
, unreg_func_list_extra
[n
]);
610 if (nickserv_conf
.sync_log
) {
611 uNode
= GetUserH(hi
->users
->nick
);
615 set_user_handle_info(hi
->users
, NULL
, 0);
618 if (nickserv_conf
.disable_nicks
)
619 send_message(notify
, bot
, "NSMSG_UNREGISTER_SUCCESS", hi
->handle
);
621 send_message(notify
, bot
, "NSMSG_UNREGISTER_NICKS_SUCCESS", hi
->handle
);
624 if (nickserv_conf
.sync_log
)
625 SyncLog("UNREGISTER %s", hi
->handle
);
627 dict_remove(nickserv_handle_dict
, hi
->handle
);
632 get_handle_info(const char *handle
)
634 return dict_find(nickserv_handle_dict
, handle
, 0);
638 get_nick_info(const char *nick
)
640 return nickserv_conf
.disable_nicks
? 0 : dict_find(nickserv_nick_dict
, nick
, 0);
644 find_handle_in_channel(struct chanNode
*channel
, struct handle_info
*handle
, struct userNode
*except
)
649 for (nn
=0; nn
<channel
->members
.used
; ++nn
) {
650 mn
= channel
->members
.list
[nn
];
651 if ((mn
->user
!= except
) && (mn
->user
->handle_info
== handle
))
658 oper_has_access(struct userNode
*user
, struct userNode
*bot
, unsigned int min_level
, unsigned int quiet
) {
659 if (!user
->handle_info
) {
661 send_message(user
, bot
, "MSG_AUTHENTICATE");
665 if (!IsOper(user
) && (!IsHelping(user
) || min_level
)) {
667 send_message(user
, bot
, "NSMSG_NO_ACCESS");
671 if (HANDLE_FLAGGED(user
->handle_info
, OPER_SUSPENDED
)) {
673 send_message(user
, bot
, "MSG_OPER_SUSPENDED");
677 if (user
->handle_info
->opserv_level
< min_level
) {
679 send_message(user
, bot
, "NSMSG_NO_ACCESS");
687 is_valid_handle(const char *handle
)
689 struct userNode
*user
;
690 /* cant register a juped nick/service nick as handle, to prevent confusion */
691 user
= GetUserH(handle
);
692 if (user
&& IsLocal(user
))
694 /* check against maximum length */
695 if (strlen(handle
) > NICKSERV_HANDLE_LEN
)
697 /* for consistency, only allow account names that could be nicks */
698 if (!is_valid_nick(handle
))
700 /* disallow account names that look like bad words */
701 if (opserv_bad_channel(handle
))
703 /* test either regex or containing all valid chars */
704 if (nickserv_conf
.valid_handle_regex_set
) {
705 int err
= regexec(&nickserv_conf
.valid_handle_regex
, handle
, 0, 0, 0);
708 buff
[regerror(err
, &nickserv_conf
.valid_handle_regex
, buff
, sizeof(buff
))] = 0;
709 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
713 return !handle
[strspn(handle
, NICKSERV_VALID_CHARS
)];
718 is_registerable_nick(const char *nick
)
720 struct userNode
*user
;
721 /* cant register a juped nick/service nick as nick, to prevent confusion */
722 user
= GetUserH(nick
);
723 if (user
&& IsLocal(user
))
725 /* for consistency, only allow nicks names that could be nicks */
726 if (!is_valid_nick(nick
))
728 /* disallow nicks that look like bad words */
729 if (opserv_bad_channel(nick
))
732 if (strlen(nick
) > NICKLEN
)
734 /* test either regex or as valid handle */
735 if (nickserv_conf
.valid_nick_regex_set
) {
736 int err
= regexec(&nickserv_conf
.valid_nick_regex
, nick
, 0, 0, 0);
739 buff
[regerror(err
, &nickserv_conf
.valid_nick_regex
, buff
, sizeof(buff
))] = 0;
740 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
746 /* this has been replaced with one in tools.c
749 is_valid_email_addr(const char *email)
751 return strchr(email, '@') != NULL;
757 visible_email_addr(struct userNode
*user
, struct handle_info
*hi
)
759 if (hi
->email_addr
) {
760 if (oper_has_access(user
, nickserv
, nickserv_conf
.email_visible_level
, 1)) {
761 return hi
->email_addr
;
771 smart_get_handle_info(struct userNode
*service
, struct userNode
*user
, const char *name
)
773 struct handle_info
*hi
;
774 struct userNode
*target
;
778 if (!(hi
= get_handle_info(++name
))) {
779 send_message(user
, service
, "MSG_HANDLE_UNKNOWN", name
);
784 if (!(target
= GetUserH(name
))) {
785 send_message(user
, service
, "MSG_NICK_UNKNOWN", name
);
788 if (IsLocal(target
)) {
789 if (IsService(target
))
790 send_message(user
, service
, "NSMSG_USER_IS_SERVICE", target
->nick
);
792 send_message(user
, service
, "MSG_USER_AUTHENTICATE", target
->nick
);
795 if (!(hi
= target
->handle_info
)) {
796 send_message(user
, service
, "MSG_USER_AUTHENTICATE", target
->nick
);
804 oper_outranks(struct userNode
*user
, struct handle_info
*hi
) {
805 if (user
->handle_info
->opserv_level
> hi
->opserv_level
)
807 if (user
->handle_info
->opserv_level
== hi
->opserv_level
) {
808 if ((user
->handle_info
->opserv_level
== 1000)
809 || (user
->handle_info
== hi
)
810 || ((user
->handle_info
->opserv_level
== 0)
811 && !(HANDLE_FLAGGED(hi
, SUPPORT_HELPER
) || HANDLE_FLAGGED(hi
, NETWORK_HELPER
))
812 && HANDLE_FLAGGED(user
->handle_info
, HELPING
))) {
816 send_message(user
, nickserv
, "MSG_USER_OUTRANKED", hi
->handle
);
821 get_victim_oper(struct userNode
*user
, const char *target
)
823 struct handle_info
*hi
;
824 if (!(hi
= smart_get_handle_info(nickserv
, user
, target
)))
826 if (HANDLE_FLAGGED(user
->handle_info
, OPER_SUSPENDED
)) {
827 send_message(user
, nickserv
, "MSG_OPER_SUSPENDED");
830 return oper_outranks(user
, hi
) ? hi
: NULL
;
834 valid_user_for(struct userNode
*user
, struct handle_info
*hi
)
838 /* If no hostmasks on the account, allow it. */
839 if (!hi
->masks
->used
)
841 /* If any hostmask matches, allow it. */
842 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
843 if (user_matches_glob(user
, hi
->masks
->list
[ii
], 0, 0))
845 /* If they are allowauthed to this account, allow it (removing the aa). */
846 if (dict_find(nickserv_allow_auth_dict
, user
->nick
, NULL
) == hi
) {
847 dict_remove(nickserv_allow_auth_dict
, user
->nick
);
850 /* The user is not allowed to use this account. */
855 valid_user_sslfp(struct userNode
*user
, struct handle_info
*hi
)
859 if (!hi
->sslfps
->used
)
864 /* If any SSL fingerprint matches, allow it. */
865 for (ii
=0; ii
<hi
->sslfps
->used
; ii
++)
866 if (!irccasecmp(user
->sslfp
, hi
->sslfps
->list
[ii
]))
869 /* No valid SSL fingerprint found. */
874 is_secure_password(const char *handle
, const char *pass
, struct userNode
*user
)
877 unsigned int cnt_digits
= 0, cnt_upper
= 0, cnt_lower
= 0;
881 if (len
< nickserv_conf
.password_min_length
) {
883 send_message(user
, nickserv
, "NSMSG_PASSWORD_SHORT", nickserv_conf
.password_min_length
);
886 if (!irccasecmp(pass
, handle
)) {
888 send_message(user
, nickserv
, "NSMSG_PASSWORD_ACCOUNT");
891 dict_find(nickserv_conf
.weak_password_dict
, pass
, &p
);
894 send_message(user
, nickserv
, "NSMSG_PASSWORD_DICTIONARY");
897 for (i
=0; i
<len
; i
++) {
898 if (isdigit(pass
[i
]))
900 if (isupper(pass
[i
]))
902 if (islower(pass
[i
]))
905 if ((cnt_lower
< nickserv_conf
.password_min_lower
)
906 || (cnt_upper
< nickserv_conf
.password_min_upper
)
907 || (cnt_digits
< nickserv_conf
.password_min_digits
)) {
909 send_message(user
, nickserv
, "NSMSG_PASSWORD_READABLE", nickserv_conf
.password_min_digits
, nickserv_conf
.password_min_upper
, nickserv_conf
.password_min_lower
);
915 static auth_func_t
*auth_func_list
;
916 static void **auth_func_list_extra
;
917 static unsigned int auth_func_size
= 0, auth_func_used
= 0;
920 reg_auth_func(auth_func_t func
, void *extra
)
922 if (auth_func_used
== auth_func_size
) {
923 if (auth_func_size
) {
924 auth_func_size
<<= 1;
925 auth_func_list
= realloc(auth_func_list
, auth_func_size
*sizeof(auth_func_t
));
926 auth_func_list_extra
= realloc(auth_func_list_extra
, auth_func_size
*sizeof(void*));
929 auth_func_list
= malloc(auth_func_size
*sizeof(auth_func_t
));
930 auth_func_list_extra
= malloc(auth_func_size
*sizeof(void*));
933 auth_func_list
[auth_func_used
] = func
;
934 auth_func_list_extra
[auth_func_used
++] = extra
;
937 static handle_rename_func_t
*rf_list
;
938 static void **rf_list_extra
;
939 static unsigned int rf_list_size
, rf_list_used
;
942 reg_handle_rename_func(handle_rename_func_t func
, void *extra
)
944 if (rf_list_used
== rf_list_size
) {
947 rf_list
= realloc(rf_list
, rf_list_size
*sizeof(rf_list
[0]));
948 rf_list_extra
= realloc(rf_list_extra
, rf_list_size
*sizeof(void*));
951 rf_list
= malloc(rf_list_size
*sizeof(rf_list
[0]));
952 rf_list_extra
= malloc(rf_list_size
*sizeof(void*));
955 rf_list
[rf_list_used
] = func
;
956 rf_list_extra
[rf_list_used
++] = extra
;
960 generate_fakehost(struct handle_info
*handle
)
962 struct userNode
*target
;
963 extern const char *hidden_host_suffix
;
964 static char buffer
[HOSTLEN
+1];
968 if (!handle
->fakehost
) {
969 data
= conf_get_data("server/hidden_host_type", RECDB_QSTRING
);
973 if ((style
== 1) || (style
== 3))
974 snprintf(buffer
, sizeof(buffer
), "%s.%s", handle
->handle
, hidden_host_suffix
);
975 else if (style
== 2) {
976 /* Due to the way fakehost is coded theres no way i can
977 get the exact user, so for now ill just take the first
979 for (target
= handle
->users
; target
; target
= target
->next_authed
)
983 snprintf(buffer
, sizeof(buffer
), "%s", target
->crypthost
);
985 strncpy(buffer
, "none", sizeof(buffer
));
988 } else if (handle
->fakehost
[0] == '.') {
989 /* A leading dot indicates the stored value is actually a title. */
990 snprintf(buffer
, sizeof(buffer
), "%s.%s.%s", handle
->handle
, handle
->fakehost
+1, nickserv_conf
.titlehost_suffix
);
993 return handle
->fakehost
;
997 apply_fakehost(struct handle_info
*handle
)
999 struct userNode
*target
;
1004 fake
= generate_fakehost(handle
);
1005 for (target
= handle
->users
; target
; target
= target
->next_authed
)
1006 assign_fakehost(target
, fake
, 1);
1009 void send_func_list(struct userNode
*user
)
1012 struct handle_info
*old_info
;
1014 old_info
= user
->handle_info
;
1016 for (n
=0; n
<auth_func_used
; n
++)
1017 auth_func_list
[n
](user
, old_info
, auth_func_list_extra
[n
]);
1021 set_user_handle_info(struct userNode
*user
, struct handle_info
*hi
, int stamp
)
1024 struct handle_info
*old_info
;
1026 /* This can happen if somebody uses COOKIE while authed, or if
1027 * they re-auth to their current handle (which is silly, but users
1028 * are like that). */
1029 if (user
->handle_info
== hi
)
1032 if (user
->handle_info
) {
1033 struct userNode
*other
;
1034 struct nick_info
* ni
;
1037 userList_remove(&curr_helpers
, user
);
1039 /* remove from next_authed linked list */
1040 if (user
->handle_info
->users
== user
) {
1041 user
->handle_info
->users
= user
->next_authed
;
1042 } else if (user
->handle_info
->users
!= NULL
) {
1043 for (other
= user
->handle_info
->users
;
1044 other
->next_authed
!= user
;
1045 other
= other
->next_authed
) ;
1046 other
->next_authed
= user
->next_authed
;
1048 /* No users authed to the account - can happen if they get
1049 * killed for authing. */
1051 /* if nobody left on old handle, and they're not an oper, remove !god */
1052 if (!user
->handle_info
->users
&& !user
->handle_info
->opserv_level
)
1053 HANDLE_CLEAR_FLAG(user
->handle_info
, HELPING
);
1054 /* record them as being last seen at this time */
1055 user
->handle_info
->lastseen
= now
;
1056 if ((ni
= get_nick_info(user
->nick
)))
1058 /* and record their hostmask */
1059 snprintf(user
->handle_info
->last_quit_host
, sizeof(user
->handle_info
->last_quit_host
), "%s@%s", user
->ident
, user
->hostname
);
1061 old_info
= user
->handle_info
;
1062 user
->handle_info
= hi
;
1063 if (hi
&& !hi
->users
&& !hi
->opserv_level
)
1064 HANDLE_CLEAR_FLAG(hi
, HELPING
);
1066 /* Call auth handlers */
1067 if (!GetUserH(user
->nick
))
1071 struct nick_info
*ni
;
1073 HANDLE_CLEAR_FLAG(hi
, FROZEN
);
1074 if (nickserv_conf
.warn_clone_auth
) {
1075 struct userNode
*other
;
1076 for (other
= hi
->users
; other
; other
= other
->next_authed
)
1077 send_message(other
, nickserv
, "NSMSG_CLONE_AUTH", user
->nick
, user
->ident
, user
->hostname
);
1080 /* Add this auth to users list of current auths */
1081 user
->next_authed
= hi
->users
;
1084 /* Add to helpers list */
1085 if (IsHelper(user
) && !userList_contains(&curr_helpers
, user
))
1086 userList_append(&curr_helpers
, user
);
1088 /* Set the fakehost */
1089 if (hi
->fakehost
|| old_info
)
1093 #ifdef WITH_PROTOCOL_P10
1094 /* Stamp users with their account name. */
1095 char *id
= hi
->handle
;
1097 const char *id
= "???";
1099 /* Mark all the nicks registered to this
1100 * account as registered nicks
1101 * - Why not just this one? -rubin */
1102 if (!nickserv_conf
.disable_nicks
) {
1103 struct nick_info
*ni2
;
1104 for (ni2
= hi
->nicks
; ni2
; ni2
= ni2
->next
) {
1105 if (!irccasecmp(user
->nick
, ni2
->nick
)) {
1106 user
->modes
|= FLAGS_REGNICK
;
1111 /* send the account to the ircd */
1112 StampUser(user
, id
, hi
->registered
);
1115 /* Stop trying to kick this user off their nick */
1116 if ((ni
= get_nick_info(user
->nick
)) && (ni
->owner
== hi
)) {
1117 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
1121 /* We cannot clear the user's account ID, unfortunately. */
1122 user
->next_authed
= NULL
;
1125 /* Call auth handlers */
1126 if (GetUserH(user
->nick
)) {
1127 for (n
=0; n
<auth_func_used
; n
++) {
1128 auth_func_list
[n
](user
, old_info
, auth_func_list_extra
[n
]);
1135 static struct handle_info
*
1136 nickserv_register(struct userNode
*user
, struct userNode
*settee
, const char *handle
, const char *passwd
, int no_auth
)
1138 struct handle_info
*hi
;
1139 struct nick_info
*ni
;
1140 char crypted
[MD5_CRYPT_LENGTH
] = "";
1142 if ((hi
= dict_find(nickserv_handle_dict
, handle
, NULL
))) {
1144 send_message(user
, nickserv
, "NSMSG_HANDLE_EXISTS", handle
);
1148 if(strlen(handle
) > 30)
1151 send_message(user
, nickserv
, "NSMSG_HANDLE_TOLONG", handle
, 30);
1157 if (!is_secure_password(handle
, passwd
, user
))
1160 cryptpass(passwd
, crypted
);
1163 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1165 rc
= ldap_do_add(handle
, (no_auth
|| !passwd
? NULL
: crypted
), NULL
);
1166 if(LDAP_SUCCESS
!= rc
&& LDAP_ALREADY_EXISTS
!= rc
) {
1168 send_message(user
, nickserv
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
1173 hi
= register_handle(handle
, crypted
, 0);
1174 hi
->masks
= alloc_string_list(1);
1175 hi
->sslfps
= alloc_string_list(1);
1176 hi
->ignores
= alloc_string_list(1);
1178 hi
->language
= lang_C
;
1179 hi
->registered
= now
;
1181 hi
->flags
= HI_DEFAULT_FLAGS
;
1182 if (settee
&& !no_auth
)
1183 set_user_handle_info(settee
, hi
, 1);
1185 if (user
!= settee
) {
1187 send_message(user
, nickserv
, "NSMSG_OREGISTER_H_SUCCESS");
1189 else if (nickserv_conf
.disable_nicks
) {
1191 send_message(user
, nickserv
, "NSMSG_REGISTER_H_SUCCESS");
1194 else if (user
&& (ni
= dict_find(nickserv_nick_dict
, user
->nick
, NULL
))) {
1196 send_message(user
, nickserv
, "NSMSG_PARTIAL_REGISTER");
1201 if (is_registerable_nick(user
->nick
)) {
1202 register_nick(user
->nick
, hi
);
1203 send_message(user
, nickserv
, "NSMSG_REGISTER_HN_SUCCESS");
1207 if (is_registerable_nick(handle
)) {
1208 register_nick(handle
, hi
);
1212 if (settee
&& (user
!= settee
)) {
1214 send_message(settee
, nickserv
, "NSMSG_OREGISTER_VICTIM", user
->nick
, hi
->handle
);
1221 nickserv_bake_cookie(struct handle_cookie
*cookie
)
1223 cookie
->hi
->cookie
= cookie
;
1224 timeq_add(cookie
->expires
, nickserv_free_cookie
, cookie
);
1227 /* Contributed by the great sneep of afternet ;) */
1228 /* Since this gets used in a URL, we want to avoid stuff that confuses
1229 * email clients such as ] and ?. a-z, 0-9 only.
1231 void genpass(char *str
, int len
)
1236 for(i
= 0; i
< len
; i
++)
1240 c
= (char)((float)rand() / (float)RAND_MAX
* (float)256);
1241 } while(!((c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z') || (c
>= '0' && c
<= '9')));
1249 nickserv_make_cookie(struct userNode
*user
, struct handle_info
*hi
, enum cookie_type type
, const char *cookie_data
, int weblink
)
1251 struct handle_cookie
*cookie
;
1252 char subject
[128], body
[4096], *misc
;
1253 const char *netname
, *fmt
;
1257 send_message(user
, nickserv
, "NSMSG_COOKIE_LIVE", hi
->handle
);
1261 cookie
= calloc(1, sizeof(*cookie
));
1263 cookie
->type
= type
;
1264 cookie
->data
= cookie_data
? strdup(cookie_data
) : NULL
;
1266 cookie
->expires
= now
+ nickserv_conf
.cookie_timeout
;
1267 /* Adding dedicated password gen function for more control -Rubin */
1268 genpass(cookie
->cookie
, 10);
1270 *inttobase64(cookie->cookie, rand(), 5);
1271 *inttobase64(cookie->cookie+5, rand(), 5);
1274 netname
= nickserv_conf
.network_name
;
1277 switch (cookie
->type
) {
1279 hi
->passwd
[0] = 0; /* invalidate password */
1280 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_REGISTER");
1281 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_SUBJECT");
1282 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1285 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_BODY_WEB");
1287 fmt
= handle_find_message(hi
, "NSEMAIL_ACTIVATION_BODY");
1289 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1292 case PASSWORD_CHANGE
:
1293 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_RESETPASS");
1294 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_SUBJECT");
1295 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1297 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_BODY_WEB");
1299 fmt
= handle_find_message(hi
, "NSEMAIL_PASSWORD_CHANGE_BODY");
1300 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1304 misc
= hi
->email_addr
;
1305 hi
->email_addr
= cookie
->data
;
1306 #ifdef stupid_verify_old_email
1308 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_EMAIL_2");
1309 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_SUBJECT");
1310 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1311 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_BODY_NEW");
1312 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
+COOKIELEN
/2, nickserv
->nick
, self
->name
, hi
->handle
, COOKIELEN
/2);
1313 mail_send(nickserv
, hi
, subject
, body
, 1);
1314 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_CHANGE_BODY_OLD");
1315 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
, COOKIELEN
/2, hi
->email_addr
);
1319 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_EMAIL_1");
1320 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_VERIFY_SUBJECT");
1321 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1322 fmt
= handle_find_message(hi
, "NSEMAIL_EMAIL_VERIFY_BODY");
1323 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1324 mail_send(nickserv
, hi
, subject
, body
, 1);
1326 #ifdef stupid_verify_old_email
1329 hi
->email_addr
= misc
;
1332 fmt
= handle_find_message(hi
, "NSEMAIL_ALLOWAUTH_SUBJECT");
1333 snprintf(subject
, sizeof(subject
), fmt
, netname
);
1334 fmt
= handle_find_message(hi
, "NSEMAIL_ALLOWAUTH_BODY");
1335 snprintf(body
, sizeof(body
), fmt
, netname
, cookie
->cookie
, nickserv
->nick
, self
->name
, hi
->handle
);
1336 send_message(user
, nickserv
, "NSMSG_USE_COOKIE_AUTH");
1339 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d in nickserv_make_cookie.", cookie
->type
);
1343 mail_send(nickserv
, hi
, subject
, body
, first_time
);
1344 nickserv_bake_cookie(cookie
);
1348 nickserv_eat_cookie(struct handle_cookie
*cookie
)
1350 cookie
->hi
->cookie
= NULL
;
1351 timeq_del(cookie
->expires
, nickserv_free_cookie
, cookie
, 0);
1352 nickserv_free_cookie(cookie
);
1356 nickserv_free_email_addr(void *data
)
1358 handle_info_list_clean(data
);
1363 nickserv_set_email_addr(struct handle_info
*hi
, const char *new_email_addr
)
1365 struct handle_info_list
*hil
;
1366 /* Remove from old handle_info_list ... */
1367 if (hi
->email_addr
&& (hil
= dict_find(nickserv_email_dict
, hi
->email_addr
, 0))) {
1368 handle_info_list_remove(hil
, hi
);
1369 if (!hil
->used
) dict_remove(nickserv_email_dict
, hil
->tag
);
1370 hi
->email_addr
= NULL
;
1372 /* Add to the new list.. */
1373 if (new_email_addr
) {
1374 if (!(hil
= dict_find(nickserv_email_dict
, new_email_addr
, 0))) {
1375 hil
= calloc(1, sizeof(*hil
));
1376 hil
->tag
= strdup(new_email_addr
);
1377 handle_info_list_init(hil
);
1378 dict_insert(nickserv_email_dict
, hil
->tag
, hil
);
1380 handle_info_list_append(hil
, hi
);
1381 hi
->email_addr
= hil
->tag
;
1385 static NICKSERV_FUNC(cmd_register
)
1388 struct handle_info
*hi
;
1389 const char *email_addr
, *password
;
1390 char syncpass
[MD5_CRYPT_LENGTH
];
1391 int no_auth
, weblink
;
1393 if (checkDefCon(DEFCON_NO_NEW_NICKS
) && !IsOper(user
)) {
1394 reply("NSMSG_DEFCON_NO_NEW_NICKS", nickserv_conf
.disable_nicks
? "accounts" : "nicknames");
1398 if (!IsOper(user
) && !dict_size(nickserv_handle_dict
)) {
1399 /* Require the first handle registered to belong to someone +o. */
1400 reply("NSMSG_REQUIRE_OPER");
1404 if (user
->handle_info
) {
1405 reply("NSMSG_USE_RENAME", user
->handle_info
->handle
);
1409 if (IsRegistering(user
)) {
1410 reply("NSMSG_ALREADY_REGISTERING");
1414 if (IsStamped(user
)) {
1415 /* Unauthenticated users might still have been stamped
1416 previously and could therefore have a hidden host;
1417 do not allow them to register a new account. */
1418 reply("NSMSG_STAMPED_REGISTER");
1422 NICKSERV_MIN_PARMS((unsigned)3 + nickserv_conf
.email_required
);
1424 if(nickserv_conf
.force_handles_lowercase
)
1425 irc_strtolower(argv
[1]);
1426 if (!is_valid_handle(argv
[1])) {
1427 reply("NSMSG_BAD_HANDLE", argv
[1]);
1432 if ((argc
>= 4) && nickserv_conf
.email_enabled
) {
1433 struct handle_info_list
*hil
;
1436 /* Remember email address. */
1437 email_addr
= argv
[3];
1439 /* Check that the email address looks valid.. */
1440 if (!valid_email(email_addr
)) {
1441 reply("NSMSG_BAD_EMAIL_ADDR");
1445 /* .. and that we are allowed to send to it. */
1446 if ((str
= mail_prohibited_address(email_addr
))) {
1447 reply("NSMSG_EMAIL_PROHIBITED", email_addr
, str
);
1451 /* If we do email verify, make sure we don't spam the address. */
1452 if ((hil
= dict_find(nickserv_email_dict
, email_addr
, NULL
))) {
1454 for (nn
=0; nn
<hil
->used
; nn
++) {
1455 if (hil
->list
[nn
]->cookie
) {
1456 reply("NSMSG_EMAIL_UNACTIVATED");
1460 if (hil
->used
>= nickserv_conf
.handles_per_email
) {
1461 reply("NSMSG_EMAIL_OVERUSED");
1474 /* Webregister hack - send URL instead of IRC cookie
1477 if((argc
>= 5) && !strcmp(argv
[4],"WEBLINK"))
1481 if (!(hi
= nickserv_register(user
, user
, argv
[1], password
, no_auth
)))
1483 /* Add any masks they should get. */
1484 if (nickserv_conf
.default_hostmask
) {
1485 string_list_append(hi
->masks
, strdup("*@*"));
1487 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
1488 if (irc_in_addr_is_valid(user
->ip
) && !irc_pton(&ip
, NULL
, user
->hostname
))
1489 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_BYIP
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
1492 /* If they're the first to register, give them level 1000. */
1493 if (dict_size(nickserv_handle_dict
) == 1) {
1494 hi
->opserv_level
= 1000;
1495 reply("NSMSG_ROOT_HANDLE", argv
[1]);
1498 /* Set their email address. */
1501 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1503 if((rc
= ldap_do_modify(hi
->handle
, NULL
, email_addr
)) != LDAP_SUCCESS
) {
1504 /* Falied to update email in ldap, but still
1505 * updated it here.. what should we do? */
1506 reply("NSMSG_LDAP_FAIL_EMAIL", ldap_err2string(rc
));
1508 nickserv_set_email_addr(hi
, email_addr
);
1512 nickserv_set_email_addr(hi
, email_addr
);
1515 nickserv_set_email_addr(hi
, email_addr
);
1519 /* If they need to do email verification, tell them. */
1521 nickserv_make_cookie(user
, hi
, ACTIVATION
, hi
->passwd
, weblink
);
1523 /* Set registering flag.. */
1524 user
->modes
|= FLAGS_REGISTERING
;
1526 if (nickserv_conf
.sync_log
) {
1527 cryptpass(password
, syncpass
);
1529 * An 0 is only sent if theres no email address. Thios should only happen if email functions are
1530 * disabled which they wont be for us. Email Required MUST be set on if you are using this.
1533 SyncLog("REGISTER %s %s %s %s", hi
->handle
, syncpass
, email_addr
? email_addr
: "0", user
->info
);
1536 /* this wont work if email is required .. */
1537 process_adduser_pending(user
);
1542 static NICKSERV_FUNC(cmd_oregister
)
1544 struct userNode
*settee
= NULL
;
1545 struct handle_info
*hi
;
1546 char* account
= NULL
;
1552 NICKSERV_MIN_PARMS(3);
1556 if(nickserv_conf
.force_handles_lowercase
)
1557 irc_strtolower(account
);
1558 if (!is_valid_handle(argv
[1])) {
1559 reply("NSMSG_BAD_HANDLE", argv
[1]);
1562 if (nickserv_conf
.email_required
) {
1563 NICKSERV_MIN_PARMS(3);
1565 if (argc
> 4) {/* take: "acct pass email mask nick" or "acct pass email mask" or "acct pass email nick" */
1566 if (strchr(argv
[4], '@'))
1576 if (argc
> 3) {/* take: "account pass mask nick" or "account pass mask" or "account pass nick" */
1577 if (strchr(argv
[3], '@'))
1586 /* If they passed a nick, look for that user.. */
1587 if (nick
&& !(settee
= GetUserH(nick
))) {
1588 reply("MSG_NICK_UNKNOWN", argv
[4]);
1591 /* If the setee is already authed, we cant add a 2nd account for them.. */
1592 if (settee
&& settee
->handle_info
) {
1593 reply("NSMSG_USER_PREV_AUTH", settee
->nick
);
1596 /* If there is no default mask in the conf, and they didn't pass a mask,
1597 * but we did find a user by nick, generate the mask */
1599 if (nickserv_conf
.default_hostmask
)
1602 mask
= generate_hostmask(settee
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
1604 reply("NSMSG_REGISTER_BAD_NICKMASK");
1609 if (!(hi
= nickserv_register(user
, settee
, account
, pass
, 0))) {
1610 return 0; /* error reply handled by above */
1614 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
1616 if((rc
= ldap_do_modify(hi
->handle
, NULL
, email
)) != LDAP_SUCCESS
) {
1617 /* Falied to update email in ldap, but still
1618 * updated it here.. what should we do? */
1619 reply("NSMSG_LDAP_FAIL_EMAIL", ldap_err2string(rc
));
1621 nickserv_set_email_addr(hi
, email
);
1625 nickserv_set_email_addr(hi
, email
);
1628 nickserv_set_email_addr(hi
, email
);
1632 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
1633 if (mask_canonicalized
)
1634 string_list_append(hi
->masks
, mask_canonicalized
);
1639 if (nickserv_conf
.sync_log
)
1640 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, email
? email
: "@", user
->info
); /* Send just @ for email if none */
1645 nickserv_ignore(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, char *mask
)
1648 struct userNode
*target
;
1649 char *new_mask
= strdup(pretty_mask(mask
));
1650 for (i
=0; i
<hi
->ignores
->used
; i
++) {
1651 if (!irccasecmp(new_mask
, hi
->ignores
->list
[i
])) {
1652 reply("NSMSG_ADDIGNORE_ALREADY", new_mask
);
1657 string_list_append(hi
->ignores
, new_mask
);
1658 reply("NSMSG_ADDIGNORE_SUCCESS", new_mask
);
1660 for (target
= hi
->users
; target
; target
= target
->next_authed
) {
1661 irc_silence(target
, new_mask
, 1);
1666 static NICKSERV_FUNC(cmd_addignore
)
1668 NICKSERV_MIN_PARMS(2);
1670 return nickserv_ignore(cmd
, user
, user
->handle_info
, argv
[1]);
1673 static NICKSERV_FUNC(cmd_oaddignore
)
1675 struct handle_info
*hi
;
1677 NICKSERV_MIN_PARMS(3);
1678 if (!(hi
= get_victim_oper(user
, argv
[1])))
1681 return nickserv_ignore(cmd
, user
, hi
, argv
[2]);
1685 nickserv_delignore(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, char *del_mask
)
1688 struct userNode
*target
;
1689 char *pmask
= strdup(pretty_mask(del_mask
));
1690 for (i
=0; i
<hi
->ignores
->used
; i
++) {
1691 if (!strcmp(pmask
, hi
->ignores
->list
[i
]) || !strcmp(del_mask
, hi
->ignores
->list
[i
])) {
1692 char *old_mask
= hi
->ignores
->list
[i
];
1693 hi
->ignores
->list
[i
] = hi
->ignores
->list
[--hi
->ignores
->used
];
1694 reply("NSMSG_DELMASK_SUCCESS", old_mask
);
1695 for (target
= hi
->users
; target
; target
= target
->next_authed
) {
1696 irc_silence(target
, old_mask
, 0);
1703 reply("NSMSG_DELMASK_NOT_FOUND");
1707 static NICKSERV_FUNC(cmd_delignore
)
1709 NICKSERV_MIN_PARMS(2);
1710 return nickserv_delignore(cmd
, user
, user
->handle_info
, argv
[1]);
1713 static NICKSERV_FUNC(cmd_odelignore
)
1715 struct handle_info
*hi
;
1716 NICKSERV_MIN_PARMS(3);
1717 if (!(hi
= get_victim_oper(user
, argv
[1])))
1719 return nickserv_delignore(cmd
, user
, hi
, argv
[2]);
1722 static NICKSERV_FUNC(cmd_handleinfo
)
1725 unsigned int i
, pos
=0, herelen
;
1726 struct userNode
*target
, *next_un
;
1727 struct handle_info
*hi
;
1728 const char *nsmsg_none
;
1731 if (!(hi
= user
->handle_info
)) {
1732 reply("NSMSG_MUST_AUTH");
1735 } else if (!(hi
= modcmd_get_handle_info(user
, argv
[1]))) {
1739 nsmsg_none
= handle_find_message(hi
, "MSG_NONE");
1740 reply("NSMSG_HANDLEINFO_ON", hi
->handle
);
1742 reply("NSMSG_HANDLEINFO_REGGED", ctime(&hi
->registered
));
1745 intervalString(buff
, now
- hi
->lastseen
, user
->handle_info
);
1746 reply("NSMSG_HANDLEINFO_LASTSEEN", buff
);
1748 reply("NSMSG_HANDLEINFO_LASTSEEN_NOW");
1751 reply("NSMSG_HANDLEINFO_INFOLINE", (hi
->infoline
? hi
->infoline
: nsmsg_none
));
1752 if (HANDLE_FLAGGED(hi
, FROZEN
))
1753 reply("NSMSG_HANDLEINFO_VACATION");
1755 if (oper_has_access(user
, cmd
->parent
->bot
, 0, 1)) {
1756 struct do_not_register
*dnr
;
1757 if ((dnr
= chanserv_is_dnr(NULL
, hi
)))
1758 reply("NSMSG_HANDLEINFO_DNR", dnr
->setter
, dnr
->reason
);
1759 if ((user
->handle_info
->opserv_level
< 900) && !oper_outranks(user
, hi
))
1761 } else if (hi
!= user
->handle_info
) {
1762 reply("NSMSG_HANDLEINFO_END");
1767 reply("NSMSG_HANDLEINFO_KARMA", hi
->karma
);
1769 if (nickserv_conf
.email_enabled
)
1770 reply("NSMSG_HANDLEINFO_EMAIL_ADDR", visible_email_addr(user
, hi
));
1774 switch (hi
->cookie
->type
) {
1775 case ACTIVATION
: type
= "NSMSG_HANDLEINFO_COOKIE_ACTIVATION"; break;
1776 case PASSWORD_CHANGE
: type
= "NSMSG_HANDLEINFO_COOKIE_PASSWORD"; break;
1777 case EMAIL_CHANGE
: type
= "NSMSG_HANDLEINFO_COOKIE_EMAIL"; break;
1778 case ALLOWAUTH
: type
= "NSMSG_HANDLEINFO_COOKIE_ALLOWAUTH"; break;
1779 default: type
= "NSMSG_HANDLEINFO_COOKIE_UNKNOWN"; break;
1782 if (IsOper(user
) && (hi
->cookie
->type
== EMAIL_CHANGE
))
1783 reply("NSMSG_HANDLEINFO_COOKIE_EMAIL_DATA", hi
->cookie
->data
);
1787 unsigned long flen
= 1;
1788 char flags
[34]; /* 32 bits possible plus '+' and '\0' */
1790 for (i
=0, flen
=1; handle_flags
[i
]; i
++)
1791 if (hi
->flags
& 1 << i
)
1792 flags
[flen
++] = handle_flags
[i
];
1794 reply("NSMSG_HANDLEINFO_FLAGS", flags
);
1796 reply("NSMSG_HANDLEINFO_FLAGS", nsmsg_none
);
1799 if (hi
->opserv_level
> 0) {
1800 reply("NSMSG_HANDLEINFO_OPSERV_LEVEL", hi
->opserv_level
);
1803 if (HANDLE_FLAGGED(hi
, SUPPORT_HELPER
)
1804 || HANDLE_FLAGGED(hi
, NETWORK_HELPER
)
1805 || (hi
->opserv_level
> 0)) {
1806 reply("NSMSG_HANDLEINFO_EPITHET", (hi
->epithet
? hi
->epithet
: nsmsg_none
));
1809 if (IsHelping(user
) || IsOper(user
))
1814 strftime(date
, 64, "%b %d %Y", localtime(&hi
->note
->date
));
1815 reply("NSMSG_HANDLEINFO_NOTE", hi
->note
->setter
, date
, hi
->note
->note
);
1820 reply("NSMSG_HANDLEINFO_FAKEHOST", (hi
->fakehost
? hi
->fakehost
: handle_find_message(hi
, "MSG_NONE")));
1822 if (hi
->last_quit_host
[0])
1823 reply("NSMSG_HANDLEINFO_LAST_HOST", hi
->last_quit_host
);
1825 reply("NSMSG_HANDLEINFO_LAST_HOST_UNKNOWN");
1827 if (nickserv_conf
.disable_nicks
) {
1828 /* nicks disabled; don't show anything about registered nicks */
1829 } else if (hi
->nicks
) {
1830 struct nick_info
*ni
, *next_ni
;
1831 for (ni
= hi
->nicks
; ni
; ni
= next_ni
) {
1832 herelen
= strlen(ni
->nick
);
1833 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1835 goto print_nicks_buff
;
1839 memcpy(buff
+pos
, ni
->nick
, herelen
);
1840 pos
+= herelen
; buff
[pos
++] = ' ';
1844 reply("NSMSG_HANDLEINFO_NICKS", buff
);
1849 reply("NSMSG_HANDLEINFO_NICKS", nsmsg_none
);
1852 if (hi
->masks
->used
) {
1853 for (i
=0; i
< hi
->masks
->used
; i
++) {
1854 herelen
= strlen(hi
->masks
->list
[i
]);
1855 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1857 goto print_mask_buff
;
1859 memcpy(buff
+pos
, hi
->masks
->list
[i
], herelen
);
1860 pos
+= herelen
; buff
[pos
++] = ' ';
1861 if (i
+1 == hi
->masks
->used
) {
1864 reply("NSMSG_HANDLEINFO_MASKS", buff
);
1869 reply("NSMSG_HANDLEINFO_MASKS", nsmsg_none
);
1872 if (hi
->sslfps
->used
) {
1873 for (i
=0; i
< hi
->sslfps
->used
; i
++) {
1874 herelen
= strlen(hi
->sslfps
->list
[i
]);
1875 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1877 goto print_sslfp_buff
;
1879 memcpy(buff
+pos
, hi
->sslfps
->list
[i
], herelen
);
1880 pos
+= herelen
; buff
[pos
++] = ' ';
1881 if (i
+1 == hi
->sslfps
->used
) {
1884 reply("NSMSG_HANDLEINFO_SSLFPS", buff
);
1889 reply("NSMSG_HANDLEINFO_SSLFPS", nsmsg_none
);
1892 if (hi
->ignores
->used
) {
1893 for (i
=0; i
< hi
->ignores
->used
; i
++) {
1894 herelen
= strlen(hi
->ignores
->list
[i
]);
1895 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1897 goto print_ignore_buff
;
1899 memcpy(buff
+pos
, hi
->ignores
->list
[i
], herelen
);
1900 pos
+= herelen
; buff
[pos
++] = ' ';
1901 if (i
+1 == hi
->ignores
->used
) {
1904 reply("NSMSG_HANDLEINFO_IGNORES", buff
);
1909 reply("NSMSG_HANDLEINFO_IGNORES", nsmsg_none
);
1913 struct userData
*chan
, *next
;
1916 for (chan
= hi
->channels
; chan
; chan
= next
) {
1917 next
= chan
->u_next
;
1918 name
= chan
->channel
->channel
->name
;
1919 herelen
= strlen(name
);
1920 if (pos
+ herelen
+ 7 > ArrayLength(buff
)) {
1922 goto print_chans_buff
;
1924 if (IsUserSuspended(chan
))
1926 pos
+= sprintf(buff
+pos
, "%s:%s ", user_level_name_from_level(chan
->access
), name
);
1930 reply("NSMSG_HANDLEINFO_CHANNELS", buff
);
1935 reply("NSMSG_HANDLEINFO_CHANNELS", nsmsg_none
);
1938 for (target
= hi
->users
; target
; target
= next_un
) {
1939 herelen
= strlen(target
->nick
);
1940 if (pos
+ herelen
+ 1 > ArrayLength(buff
)) {
1942 goto print_cnick_buff
;
1944 next_un
= target
->next_authed
;
1946 memcpy(buff
+pos
, target
->nick
, herelen
);
1947 pos
+= herelen
; buff
[pos
++] = ' ';
1951 reply("NSMSG_HANDLEINFO_CURRENT", buff
);
1956 reply("NSMSG_HANDLEINFO_END");
1957 return 1 | ((hi
!= user
->handle_info
) ? CMD_LOG_STAFF
: 0);
1960 static NICKSERV_FUNC(cmd_userinfo
)
1962 struct userNode
*target
;
1964 NICKSERV_MIN_PARMS(2);
1965 if (!(target
= GetUserH(argv
[1]))) {
1966 reply("MSG_NICK_UNKNOWN", argv
[1]);
1969 if (target
->handle_info
)
1970 reply("NSMSG_USERINFO_AUTHED_AS", target
->nick
, target
->handle_info
->handle
);
1972 reply("NSMSG_USERINFO_NOT_AUTHED", target
->nick
);
1976 static NICKSERV_FUNC(cmd_nickinfo
)
1978 struct nick_info
*ni
;
1981 NICKSERV_MIN_PARMS(2);
1982 if (!(ni
= get_nick_info(argv
[1]))) {
1983 reply("MSG_NICK_UNKNOWN", argv
[1]);
1987 reply("NSMSG_NICKINFO_ON", ni
->nick
);
1989 reply("NSMSG_NICKINFO_REGGED", ctime(&ni
->registered
));
1991 if (!GetUserH(ni
->nick
)) {
1992 intervalString(buff
, now
- ni
->lastseen
, user
->handle_info
);
1993 reply("NSMSG_NICKINFO_LASTSEEN", buff
);
1995 reply("NSMSG_NICKINFO_LASTSEEN_NOW");
1998 reply("NSMSG_NICKINFO_OWNER", ni
->owner
->handle
);
2000 reply("NSMSG_NICKINFO_END");
2005 static NICKSERV_FUNC(cmd_rename_handle
)
2007 struct handle_info
*hi
;
2008 struct userNode
*uNode
;
2012 NICKSERV_MIN_PARMS(3);
2013 if(nickserv_conf
.force_handles_lowercase
)
2014 irc_strtolower(argv
[2]);
2015 if (!(hi
= get_victim_oper(user
, argv
[1])))
2017 if (!is_valid_handle(argv
[2])) {
2018 reply("NSMSG_FAIL_RENAME", argv
[1], argv
[2]);
2021 if (get_handle_info(argv
[2])) {
2022 reply("NSMSG_HANDLE_EXISTS", argv
[2]);
2025 if(strlen(argv
[2]) > 30)
2027 reply("NMSG_HANDLE_TOLONG", argv
[2], 30);
2031 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2033 if( (rc
= ldap_rename_account(hi
->handle
, argv
[2])) != LDAP_SUCCESS
) {
2034 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2040 dict_remove2(nickserv_handle_dict
, old_handle
= hi
->handle
, 1);
2041 hi
->handle
= strdup(argv
[2]);
2042 dict_insert(nickserv_handle_dict
, hi
->handle
, hi
);
2043 for (nn
=0; nn
<rf_list_used
; nn
++)
2044 rf_list
[nn
](hi
, old_handle
, rf_list_extra
[nn
]);
2046 if (nickserv_conf
.sync_log
) {
2047 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
2048 irc_rename(uNode
, hi
->handle
);
2050 SyncLog("RENAME %s %s", old_handle
, hi
->handle
);
2053 reply("NSMSG_HANDLE_CHANGED", old_handle
, hi
->handle
);
2054 global_message_args(MESSAGE_RECIPIENT_OPERS
, "NSMSG_ACCOUNT_RENAMED",
2055 user
->handle_info
->handle
, old_handle
, hi
->handle
);
2061 static failpw_func_t
*failpw_func_list
;
2062 static void **failpw_func_list_extra
;
2063 static unsigned int failpw_func_size
= 0, failpw_func_used
= 0;
2066 reg_failpw_func(failpw_func_t func
, void *extra
)
2068 if (failpw_func_used
== failpw_func_size
) {
2069 if (failpw_func_size
) {
2070 failpw_func_size
<<= 1;
2071 failpw_func_list
= realloc(failpw_func_list
, failpw_func_size
*sizeof(failpw_func_t
));
2072 failpw_func_list_extra
= realloc(failpw_func_list_extra
, failpw_func_size
*sizeof(void*));
2074 failpw_func_size
= 8;
2075 failpw_func_list
= malloc(failpw_func_size
*sizeof(failpw_func_t
));
2076 failpw_func_list_extra
= malloc(failpw_func_size
*sizeof(void*));
2079 failpw_func_list
[failpw_func_used
] = func
;
2080 failpw_func_list_extra
[failpw_func_used
++] = extra
;
2084 * Return hi for the first handle that has a matching SSL fingerprint.
2086 struct handle_info
*find_handleinfo_by_sslfp(char *sslfp
)
2089 struct handle_info
*hi
;
2090 unsigned int ii
= 0;;
2092 for (it
= dict_first(nickserv_handle_dict
); it
; it
= iter_next(it
)) {
2094 for (ii
=0; ii
<hi
->sslfps
->used
; ii
++) {
2095 if (!irccasecmp(sslfp
, hi
->sslfps
->list
[ii
])) {
2105 * Return hi if the handle/pass pair matches, NULL if it doesnt.
2107 * called by nefariouses enhanced AC login-on-connect code
2110 struct handle_info
*loc_auth(char *sslfp
, char *handle
, char *password
, char *userhost
)
2112 int wildmask
= 0, auth
= 0;
2113 int used
, maxlogins
;
2115 struct handle_info
*hi
= NULL
;
2116 struct userNode
*other
;
2118 int ldap_result
= LDAP_SUCCESS
;
2123 hi
= dict_find(nickserv_handle_dict
, handle
, NULL
);
2124 if (!hi
&& (sslfp
!= NULL
)) {
2125 hi
= find_handleinfo_by_sslfp(sslfp
);
2126 if (!handle
&& (hi
!= NULL
))
2127 handle
= hi
->handle
;
2130 /* Ensure handle is valid if not found in internal DB */
2131 if (!hi
&& (!handle
|| !is_valid_handle(handle
)))
2135 if (nickserv_conf
.ldap_enable
&& (password
!= NULL
)) {
2136 ldap_result
= ldap_check_auth(handle
, password
);
2137 if (!hi
&& (ldap_result
!= LDAP_SUCCESS
))
2139 if (ldap_result
== LDAP_SUCCESS
) {
2140 /* Mark auth as successful */
2144 if (!hi
&& (ldap_result
== LDAP_SUCCESS
) && nickserv_conf
.ldap_autocreate
) {
2145 /* user not found, but authed to ldap successfully..
2146 * create the account.
2151 /* Add a *@* mask */
2152 /* TODO if userhost is not null, build mask based on that. */
2153 if(nickserv_conf
.default_hostmask
)
2156 return NULL
; /* They dont have a *@* mask so they can't loc */
2158 if(!(hi
= nickserv_register(NULL
, NULL
, handle
, password
, 0))) {
2159 return 0; /* couldn't add the user for some reason */
2162 if((rc
= ldap_get_user_info(handle
, &email
) != LDAP_SUCCESS
))
2164 if(nickserv_conf
.email_required
) {
2169 nickserv_set_email_addr(hi
, email
);
2173 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
2174 string_list_append(hi
->masks
, mask_canonicalized
);
2176 if(nickserv_conf
.sync_log
)
2177 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, "@", handle
);
2182 /* hi should now be a valid handle, if not return NULL */
2187 if (password
&& *password
&& !nickserv_conf
.ldap_enable
) {
2189 if (password
&& *password
) {
2191 if (checkpass(password
, hi
->passwd
))
2195 if (!auth
&& sslfp
&& *sslfp
&& hi
->sslfps
->used
) {
2196 /* If any SSL fingerprint matches, allow it. */
2197 for (ii
=0; ii
<hi
->sslfps
->used
; ii
++) {
2198 if (!irccasecmp(sslfp
, hi
->sslfps
->list
[ii
])) {
2205 /* Auth should have succeeded by this point */
2209 /* We don't know the users hostname, or anything because they
2210 * havn't registered yet. So we can only allow LOC if your
2211 * account has *@* as a hostmask.
2213 * UPDATE: New nefarious LOC supports u@h
2218 char *realhost
= NULL
;
2225 buf
= strdup(userhost
);
2228 for (c
= buf
; *c
; c
++) {
2229 if ((realhost
== NULL
) && (*c
== '@')) {
2236 } else if (bracket
&& (ip
== NULL
) && (*c
== ']')) {
2239 } else if (!bracket
&& (ip
== NULL
) && (*c
== ':')) {
2246 log_module(NS_LOG
, LOG_DEBUG
, "LOC: ident=%s host=%s ip=%s", ident
, realhost
, ip
);
2248 if(!ip
|| !realhost
|| !ident
) {
2250 return NULL
; /* Invalid AC request, just quit */
2252 uh
= malloc(strlen(userhost
));
2253 ui
= malloc(strlen(userhost
));
2254 sprintf(uh
, "%s@%s", ident
, realhost
);
2255 sprintf(ui
, "%s@%s", ident
, ip
);
2256 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
2258 if(match_ircglob(uh
, hi
->masks
->list
[ii
])
2259 || match_ircglob(ui
, hi
->masks
->list
[ii
]))
2271 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
2273 if (!strcmp(hi
->masks
->list
[ii
], "*@*"))
2283 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2287 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
2288 for (used
= 0, other
= hi
->users
; other
; other
= other
->next_authed
) {
2289 if (++used
>= maxlogins
) {
2293 /* TODO - Add LOGGING to this function so LOC's are logged.. */
2297 static NICKSERV_FUNC(cmd_auth
)
2299 int pw_arg
, used
, maxlogins
;
2301 struct handle_info
*hi
;
2304 struct userNode
*other
;
2306 int ldap_result
= LDAP_OTHER
;
2310 if (user
->handle_info
) {
2311 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2314 if (IsStamped(user
)) {
2315 /* Unauthenticated users might still have been stamped
2316 previously and could therefore have a hidden host;
2317 do not allow them to authenticate. */
2318 reply("NSMSG_STAMPED_AUTH");
2325 hi
= dict_find(nickserv_handle_dict
, argv
[1], NULL
);
2326 } else if (argc
== 2) {
2329 if (nickserv_conf
.disable_nicks
) {
2330 hi
= get_handle_info(user
->nick
);
2332 /* try to look up their handle from their nick */
2333 /* TODO: handle ldap auth on nickserv style networks, too */
2334 struct nick_info
*ni
;
2335 ni
= get_nick_info(user
->nick
);
2337 reply("NSMSG_NICK_NOT_REGISTERED", user
->nick
);
2343 handle
= hi
->handle
;
2345 handle
= user
->nick
;
2348 reply("MSG_MISSING_PARAMS", argv
[0]);
2349 svccmd_send_help_brief(user
, nickserv
, cmd
);
2354 if(strchr(handle
, '<') || strchr(handle
, '>')) {
2355 reply("NSMSG_NO_ANGLEBRACKETS");
2358 if (!is_valid_handle(handle
)) {
2359 reply("NSMSG_BAD_HANDLE", handle
);
2363 if(nickserv_conf
.ldap_enable
) {
2364 ldap_result
= ldap_check_auth(handle
, passwd
);
2365 /* Get the users email address and update it */
2366 if(ldap_result
== LDAP_SUCCESS
) {
2368 if((rc
= ldap_get_user_info(handle
, &email
) != LDAP_SUCCESS
))
2370 if(nickserv_conf
.email_required
) {
2371 reply("NSMSG_LDAP_FAIL_GET_EMAIL", ldap_err2string(rc
));
2376 else if(ldap_result
!= LDAP_INVALID_CREDENTIALS
) {
2377 reply("NSMSG_LDAP_FAIL", ldap_err2string(ldap_result
));
2385 if(nickserv_conf
.ldap_enable
&& ldap_result
== LDAP_SUCCESS
&& nickserv_conf
.ldap_autocreate
) {
2386 /* user not found, but authed to ldap successfully..
2387 * create the account.
2390 if(!(hi
= nickserv_register(user
, user
, handle
, passwd
, 0))) {
2391 reply("NSMSG_UNABLE_TO_ADD");
2392 return 0; /* couldn't add the user for some reason */
2394 /* Add a *@* mask */
2395 if(nickserv_conf
.default_hostmask
)
2398 mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2401 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
2402 string_list_append(hi
->masks
, mask_canonicalized
);
2405 nickserv_set_email_addr(hi
, email
);
2408 if(nickserv_conf
.sync_log
)
2409 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, email
? email
: "@", user
->info
);
2413 reply("NSMSG_HANDLE_NOT_FOUND");
2419 /* Responses from here on look up the language used by the handle they asked about. */
2420 if (!valid_user_for(user
, hi
)) {
2421 if (hi
->email_addr
&& nickserv_conf
.email_enabled
)
2422 send_message_type(4, user
, cmd
->parent
->bot
,
2423 handle_find_message(hi
, "NSMSG_USE_AUTHCOOKIE"),
2426 send_message_type(4, user
, cmd
->parent
->bot
,
2427 handle_find_message(hi
, "NSMSG_HOSTMASK_INVALID"),
2429 argv
[pw_arg
] = "BADMASK";
2433 if (valid_user_sslfp(user
, hi
))
2437 if(( ( nickserv_conf
.ldap_enable
&& ldap_result
== LDAP_INVALID_CREDENTIALS
) ||
2438 ( (!nickserv_conf
.ldap_enable
) && (!checkpass(passwd
, hi
->passwd
)) ) ) && !sslfpauth
) {
2440 if (!checkpass(passwd
, hi
->passwd
) && !sslfpauth
) {
2443 send_message_type(4, user
, cmd
->parent
->bot
,
2444 handle_find_message(hi
, "NSMSG_PASSWORD_INVALID"));
2445 argv
[pw_arg
] = "BADPASS";
2446 for (n
=0; n
<failpw_func_used
; n
++)
2447 failpw_func_list
[n
](user
, hi
, failpw_func_list_extra
[n
]);
2448 if (nickserv_conf
.autogag_enabled
) {
2449 if (!user
->auth_policer
.params
) {
2450 user
->auth_policer
.last_req
= now
;
2451 user
->auth_policer
.params
= nickserv_conf
.auth_policer_params
;
2453 if (!policer_conforms(&user
->auth_policer
, now
, 1.0)) {
2455 hostmask
= generate_hostmask(user
, GENMASK_STRICT_HOST
|GENMASK_BYIP
|GENMASK_NO_HIDING
);
2456 log_module(NS_LOG
, LOG_INFO
, "%s auto-gagged for repeated password guessing.", hostmask
);
2457 gag_create(hostmask
, nickserv
->nick
, "Repeated password guessing.", now
+nickserv_conf
.autogag_duration
);
2459 argv
[pw_arg
] = "GAGGED";
2464 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2465 send_message_type(4, user
, cmd
->parent
->bot
,
2466 handle_find_message(hi
, "NSMSG_HANDLE_SUSPENDED"));
2467 argv
[pw_arg
] = "SUSPENDED";
2470 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
2471 for (used
= 0, other
= hi
->users
; other
; other
= other
->next_authed
) {
2472 if (++used
>= maxlogins
) {
2473 send_message_type(4, user
, cmd
->parent
->bot
,
2474 handle_find_message(hi
, "NSMSG_MAX_LOGINS"),
2476 argv
[pw_arg
] = "MAXLOGINS";
2481 set_user_handle_info(user
, hi
, 1);
2482 if (nickserv_conf
.email_required
&& !hi
->email_addr
)
2483 reply("NSMSG_PLEASE_SET_EMAIL");
2484 if (!sslfpauth
&& !is_secure_password(hi
->handle
, passwd
, NULL
))
2485 reply("NSMSG_WEAK_PASSWORD");
2486 if (!sslfpauth
&& (hi
->passwd
[0] != '$'))
2487 cryptpass(passwd
, hi
->passwd
);
2489 /* If a channel was waiting for this user to auth,
2490 * finish adding them */
2491 process_adduser_pending(user
);
2493 reply("NSMSG_AUTH_SUCCESS");
2496 /* Set +x if autohide is on */
2497 if(HANDLE_FLAGGED(hi
, AUTOHIDE
))
2498 irc_umode(user
, "+x");
2500 if (!hi
->masks
->used
) {
2502 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
2503 if (irc_in_addr_is_valid(user
->ip
) && irc_pton(&ip
, NULL
, user
->hostname
))
2504 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_BYIP
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
2507 /* Wipe out the pass for the logs */
2508 argv
[pw_arg
] = "****";
2512 static allowauth_func_t
*allowauth_func_list
;
2513 static void **allowauth_func_list_extra
;
2514 static unsigned int allowauth_func_size
= 0, allowauth_func_used
= 0;
2517 reg_allowauth_func(allowauth_func_t func
, void *extra
)
2519 if (allowauth_func_used
== allowauth_func_size
) {
2520 if (allowauth_func_size
) {
2521 allowauth_func_size
<<= 1;
2522 allowauth_func_list
= realloc(allowauth_func_list
, allowauth_func_size
*sizeof(allowauth_func_t
));
2523 allowauth_func_list_extra
= realloc(allowauth_func_list_extra
, allowauth_func_size
*sizeof(void*));
2525 allowauth_func_size
= 8;
2526 allowauth_func_list
= malloc(allowauth_func_size
*sizeof(allowauth_func_t
));
2527 allowauth_func_list_extra
= malloc(allowauth_func_size
*sizeof(void*));
2530 allowauth_func_list
[allowauth_func_used
] = func
;
2531 allowauth_func_list_extra
[allowauth_func_used
++] = extra
;
2534 static NICKSERV_FUNC(cmd_allowauth
)
2536 struct userNode
*target
;
2537 struct handle_info
*hi
;
2540 NICKSERV_MIN_PARMS(2);
2541 if (!(target
= GetUserH(argv
[1]))) {
2542 reply("MSG_NICK_UNKNOWN", argv
[1]);
2545 if (target
->handle_info
) {
2546 reply("NSMSG_USER_PREV_AUTH", target
->nick
);
2549 if (IsStamped(target
)) {
2550 /* Unauthenticated users might still have been stamped
2551 previously and could therefore have a hidden host;
2552 do not allow them to authenticate to an account. */
2553 reply("NSMSG_USER_PREV_STAMP", target
->nick
);
2558 else if (!(hi
= get_handle_info(argv
[2]))) {
2559 reply("MSG_HANDLE_UNKNOWN", argv
[2]);
2563 if (hi
->opserv_level
> user
->handle_info
->opserv_level
) {
2564 reply("MSG_USER_OUTRANKED", hi
->handle
);
2567 if (((hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
))
2568 || (hi
->opserv_level
> 0))
2569 && ((argc
< 4) || irccasecmp(argv
[3], "staff"))) {
2570 reply("NSMSG_ALLOWAUTH_STAFF", hi
->handle
);
2573 dict_insert(nickserv_allow_auth_dict
, target
->nick
, hi
);
2574 reply("NSMSG_AUTH_ALLOWED", target
->nick
, hi
->handle
);
2575 send_message(target
, nickserv
, "NSMSG_AUTH_ALLOWED_MSG", hi
->handle
, hi
->handle
);
2576 if (nickserv_conf
.email_enabled
)
2577 send_message(target
, nickserv
, "NSMSG_AUTH_ALLOWED_EMAIL");
2579 if (dict_remove(nickserv_allow_auth_dict
, target
->nick
))
2580 reply("NSMSG_AUTH_NORMAL_ONLY", target
->nick
);
2582 reply("NSMSG_AUTH_UNSPECIAL", target
->nick
);
2584 for (n
=0; n
<allowauth_func_used
; n
++)
2585 allowauth_func_list
[n
](user
, target
, hi
, allowauth_func_list_extra
[n
]);
2589 static NICKSERV_FUNC(cmd_authcookie
)
2591 struct handle_info
*hi
;
2593 NICKSERV_MIN_PARMS(2);
2594 if (user
->handle_info
) {
2595 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2598 if (IsStamped(user
)) {
2599 /* Unauthenticated users might still have been stamped
2600 previously and could therefore have a hidden host;
2601 do not allow them to authenticate to an account. */
2602 reply("NSMSG_STAMPED_AUTHCOOKIE");
2605 if (!(hi
= get_handle_info(argv
[1]))) {
2606 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2609 if (!hi
->email_addr
) {
2610 reply("MSG_SET_EMAIL_ADDR");
2613 nickserv_make_cookie(user
, hi
, ALLOWAUTH
, NULL
, 0);
2617 static NICKSERV_FUNC(cmd_delcookie
)
2619 struct handle_info
*hi
;
2621 hi
= user
->handle_info
;
2623 reply("NSMSG_NO_COOKIE");
2626 switch (hi
->cookie
->type
) {
2629 reply("NSMSG_MUST_TIME_OUT");
2632 nickserv_eat_cookie(hi
->cookie
);
2633 reply("NSMSG_ATE_COOKIE");
2639 static NICKSERV_FUNC(cmd_odelcookie
)
2641 struct handle_info
*hi
;
2643 NICKSERV_MIN_PARMS(2);
2645 if (!(hi
= get_victim_oper(user
, argv
[1])))
2649 reply("NSMSG_NO_COOKIE_FOREIGN", hi
->handle
);
2653 switch (hi
->cookie
->type
) {
2655 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2657 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2659 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2660 /* Falied to update password in ldap, but still
2661 * updated it here.. what should we do? */
2662 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2667 if (nickserv_conf
.sync_log
)
2668 SyncLog("ACCOUNTACC %s", hi
->handle
);
2670 case PASSWORD_CHANGE
:
2677 reply("NSMSG_BAD_COOKIE_TYPE", hi
->cookie
->type
);
2678 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d for account %s.", hi
->cookie
->type
, hi
->handle
);
2682 nickserv_eat_cookie(hi
->cookie
);
2683 reply("NSMSG_ATE_FOREIGN_COOKIE", hi
->handle
);
2688 static NICKSERV_FUNC(cmd_resetpass
)
2690 struct handle_info
*hi
;
2691 char crypted
[MD5_CRYPT_LENGTH
];
2694 NICKSERV_MIN_PARMS(3);
2695 if(argc
>= 4 && !strcmp(argv
[3], "WEBLINK"))
2699 if (user
->handle_info
) {
2700 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2703 if (IsStamped(user
)) {
2704 /* Unauthenticated users might still have been stamped
2705 previously and could therefore have a hidden host;
2706 do not allow them to activate an account. */
2707 reply("NSMSG_STAMPED_RESETPASS");
2710 if (!(hi
= get_handle_info(argv
[1]))) {
2711 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2714 if (!hi
->email_addr
) {
2715 reply("MSG_SET_EMAIL_ADDR");
2718 cryptpass(argv
[2], crypted
);
2720 nickserv_make_cookie(user
, hi
, PASSWORD_CHANGE
, crypted
, weblink
);
2724 static NICKSERV_FUNC(cmd_cookie
)
2726 struct handle_info
*hi
;
2729 if ((argc
== 2) && (hi
= user
->handle_info
) && hi
->cookie
&& (hi
->cookie
->type
== EMAIL_CHANGE
)) {
2732 NICKSERV_MIN_PARMS(3);
2733 if (!(hi
= get_handle_info(argv
[1]))) {
2734 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2740 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2741 reply("NSMSG_HANDLE_SUSPENDED");
2746 reply("NSMSG_NO_COOKIE");
2750 /* Check validity of operation before comparing cookie to
2751 * prohibit guessing by authed users. */
2752 if (user
->handle_info
2753 && (hi
->cookie
->type
!= EMAIL_CHANGE
)
2754 && (hi
->cookie
->type
!= PASSWORD_CHANGE
)) {
2755 reply("NSMSG_CANNOT_COOKIE");
2759 if (strcmp(cookie
, hi
->cookie
->cookie
)) {
2760 reply("NSMSG_BAD_COOKIE");
2764 switch (hi
->cookie
->type
) {
2767 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2769 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2770 /* Falied to update email in ldap, but still
2771 * updated it here.. what should we do? */
2772 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2777 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2778 set_user_handle_info(user
, hi
, 1);
2779 reply("NSMSG_HANDLE_ACTIVATED");
2780 if (nickserv_conf
.sync_log
)
2781 SyncLog("ACCOUNTACC %s", hi
->handle
);
2783 case PASSWORD_CHANGE
:
2785 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2787 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2788 /* Falied to update email in ldap, but still
2789 * updated it here.. what should we do? */
2790 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2795 set_user_handle_info(user
, hi
, 1);
2796 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2797 reply("NSMSG_PASSWORD_CHANGED");
2798 if (nickserv_conf
.sync_log
)
2799 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
2803 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2805 if((rc
= ldap_do_modify(hi
->handle
, NULL
, hi
->cookie
->data
)) != LDAP_SUCCESS
) {
2806 /* Falied to update email in ldap, but still
2807 * updated it here.. what should we do? */
2808 reply("NSMSG_LDAP_FAIL_SEND_EMAIL", ldap_err2string(rc
));
2813 if (!hi
->email_addr
&& nickserv_conf
.sync_log
) {
2815 * This should only happen if an OREGISTER was sent. Require
2816 * email must be enabled! - SiRVulcaN
2818 if (nickserv_conf
.sync_log
)
2819 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, hi
->cookie
->data
, user
->info
);
2822 nickserv_set_email_addr(hi
, hi
->cookie
->data
);
2823 reply("NSMSG_EMAIL_CHANGED");
2824 if (nickserv_conf
.sync_log
)
2825 SyncLog("EMAILCHANGE %s %s", hi
->handle
, hi
->cookie
->data
);
2828 char *mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2829 set_user_handle_info(user
, hi
, 1);
2830 nickserv_addmask(user
, hi
, mask
);
2831 reply("NSMSG_AUTH_SUCCESS");
2836 reply("NSMSG_BAD_COOKIE_TYPE", hi
->cookie
->type
);
2837 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d for account %s.", hi
->cookie
->type
, hi
->handle
);
2841 nickserv_eat_cookie(hi
->cookie
);
2843 process_adduser_pending(user
);
2848 static NICKSERV_FUNC(cmd_oregnick
) {
2850 struct handle_info
*target
;
2851 struct nick_info
*ni
;
2853 NICKSERV_MIN_PARMS(3);
2854 if (!(target
= modcmd_get_handle_info(user
, argv
[1])))
2857 if (!is_registerable_nick(nick
)) {
2858 reply("NSMSG_BAD_NICK", nick
);
2861 ni
= dict_find(nickserv_nick_dict
, nick
, NULL
);
2863 reply("NSMSG_NICK_EXISTS", nick
);
2866 register_nick(nick
, target
);
2867 reply("NSMSG_OREGNICK_SUCCESS", nick
, target
->handle
);
2871 static NICKSERV_FUNC(cmd_regnick
) {
2873 struct nick_info
*ni
;
2875 if (!is_registerable_nick(user
->nick
)) {
2876 reply("NSMSG_BAD_NICK", user
->nick
);
2879 /* count their nicks, see if it's too many */
2880 for (n
=0,ni
=user
->handle_info
->nicks
; ni
; n
++,ni
=ni
->next
) ;
2881 if (n
>= nickserv_conf
.nicks_per_handle
) {
2882 reply("NSMSG_TOO_MANY_NICKS");
2885 ni
= dict_find(nickserv_nick_dict
, user
->nick
, NULL
);
2887 reply("NSMSG_NICK_EXISTS", user
->nick
);
2890 register_nick(user
->nick
, user
->handle_info
);
2891 reply("NSMSG_REGNICK_SUCCESS", user
->nick
);
2895 static NICKSERV_FUNC(cmd_pass
)
2897 struct handle_info
*hi
;
2898 char *old_pass
, *new_pass
;
2899 char crypted
[MD5_CRYPT_LENGTH
+1];
2904 NICKSERV_MIN_PARMS(3);
2905 hi
= user
->handle_info
;
2909 if (!is_secure_password(hi
->handle
, new_pass
, user
)) return 0;
2912 if(nickserv_conf
.ldap_enable
) {
2913 ldap_result
= ldap_check_auth(hi
->handle
, old_pass
);
2914 if(ldap_result
!= LDAP_SUCCESS
) {
2915 if(ldap_result
== LDAP_INVALID_CREDENTIALS
)
2916 reply("NSMSG_PASSWORD_INVALID");
2918 reply("NSMSG_LDAP_FAIL", ldap_err2string(ldap_result
));
2923 if (!checkpass(old_pass
, hi
->passwd
)) {
2924 argv
[1] = "BADPASS";
2925 reply("NSMSG_PASSWORD_INVALID");
2928 cryptpass(new_pass
, crypted
);
2930 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2932 if((rc
= ldap_do_modify(hi
->handle
, crypted
, NULL
)) != LDAP_SUCCESS
) {
2933 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2938 //cryptpass(new_pass, hi->passwd);
2939 strcpy(hi
->passwd
, crypted
);
2940 if (nickserv_conf
.sync_log
)
2941 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
2943 reply("NSMSG_PASS_SUCCESS");
2948 nickserv_addmask(struct userNode
*user
, struct handle_info
*hi
, const char *mask
)
2951 char *new_mask
= canonicalize_hostmask(strdup(mask
));
2952 for (i
=0; i
<hi
->masks
->used
; i
++) {
2953 if (!irccasecmp(new_mask
, hi
->masks
->list
[i
])) {
2954 send_message(user
, nickserv
, "NSMSG_ADDMASK_ALREADY", new_mask
);
2959 string_list_append(hi
->masks
, new_mask
);
2960 send_message(user
, nickserv
, "NSMSG_ADDMASK_SUCCESS", new_mask
);
2964 static NICKSERV_FUNC(cmd_addmask
)
2967 char *mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2968 int res
= nickserv_addmask(user
, user
->handle_info
, mask
);
2972 if (!is_gline(argv
[1])) {
2973 reply("NSMSG_MASK_INVALID", argv
[1]);
2976 return nickserv_addmask(user
, user
->handle_info
, argv
[1]);
2980 static NICKSERV_FUNC(cmd_oaddmask
)
2982 struct handle_info
*hi
;
2984 NICKSERV_MIN_PARMS(3);
2985 if (!(hi
= get_victim_oper(user
, argv
[1])))
2987 return nickserv_addmask(user
, hi
, argv
[2]);
2991 nickserv_delmask(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, const char *del_mask
, int force
)
2994 for (i
=0; i
<hi
->masks
->used
; i
++) {
2995 if (!strcmp(del_mask
, hi
->masks
->list
[i
])) {
2996 char *old_mask
= hi
->masks
->list
[i
];
2997 if (hi
->masks
->used
== 1 && !force
) {
2998 reply("NSMSG_DELMASK_NOTLAST");
3001 hi
->masks
->list
[i
] = hi
->masks
->list
[--hi
->masks
->used
];
3002 reply("NSMSG_DELMASK_SUCCESS", old_mask
);
3007 reply("NSMSG_DELMASK_NOT_FOUND");
3011 static NICKSERV_FUNC(cmd_delmask
)
3013 NICKSERV_MIN_PARMS(2);
3014 return nickserv_delmask(cmd
, user
, user
->handle_info
, argv
[1], 0);
3017 static NICKSERV_FUNC(cmd_odelmask
)
3019 struct handle_info
*hi
;
3020 NICKSERV_MIN_PARMS(3);
3021 if (!(hi
= get_victim_oper(user
, argv
[1])))
3023 return nickserv_delmask(cmd
, user
, hi
, argv
[2], 1);
3027 nickserv_addsslfp(struct userNode
*user
, struct handle_info
*hi
, const char *sslfp
)
3030 char *new_sslfp
= strdup(sslfp
);
3031 for (i
=0; i
<hi
->sslfps
->used
; i
++) {
3032 if (!irccasecmp(new_sslfp
, hi
->sslfps
->list
[i
])) {
3033 send_message(user
, nickserv
, "NSMSG_ADDSSLFP_ALREADY", new_sslfp
);
3038 string_list_append(hi
->sslfps
, new_sslfp
);
3039 send_message(user
, nickserv
, "NSMSG_ADDSSLFP_SUCCESS", new_sslfp
);
3043 static NICKSERV_FUNC(cmd_addsslfp
)
3045 NICKSERV_MIN_PARMS((user
->sslfp
? 1 : 2));
3046 if ((argc
< 2) && (user
->sslfp
)) {
3047 int res
= nickserv_addsslfp(user
, user
->handle_info
, user
->sslfp
);
3050 return nickserv_addsslfp(user
, user
->handle_info
, argv
[1]);
3054 static NICKSERV_FUNC(cmd_oaddsslfp
)
3056 struct handle_info
*hi
;
3058 NICKSERV_MIN_PARMS(3);
3059 if (!(hi
= get_victim_oper(user
, argv
[1])))
3061 return nickserv_addsslfp(user
, hi
, argv
[2]);
3065 nickserv_delsslfp(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, const char *del_sslfp
)
3068 for (i
=0; i
<hi
->sslfps
->used
; i
++) {
3069 if (!irccasecmp(del_sslfp
, hi
->sslfps
->list
[i
])) {
3070 char *old_sslfp
= hi
->sslfps
->list
[i
];
3071 hi
->sslfps
->list
[i
] = hi
->sslfps
->list
[--hi
->sslfps
->used
];
3072 reply("NSMSG_DELSSLFP_SUCCESS", old_sslfp
);
3077 reply("NSMSG_DELSSLFP_NOT_FOUND");
3081 static NICKSERV_FUNC(cmd_delsslfp
)
3083 NICKSERV_MIN_PARMS((user
->sslfp
? 1 : 2));
3084 if ((argc
< 2) && (user
->sslfp
)) {
3085 return nickserv_delsslfp(cmd
, user
, user
->handle_info
, user
->sslfp
);
3087 return nickserv_delsslfp(cmd
, user
, user
->handle_info
, argv
[1]);
3091 static NICKSERV_FUNC(cmd_odelsslfp
)
3093 struct handle_info
*hi
;
3094 NICKSERV_MIN_PARMS(3);
3095 if (!(hi
= get_victim_oper(user
, argv
[1])))
3097 return nickserv_delsslfp(cmd
, user
, hi
, argv
[2]);
3101 nickserv_modify_handle_flags(struct userNode
*user
, struct userNode
*bot
, const char *str
, unsigned long *padded
, unsigned long *premoved
) {
3102 unsigned int nn
, add
= 1, pos
;
3103 unsigned long added
, removed
, flag
;
3105 for (added
=removed
=nn
=0; str
[nn
]; nn
++) {
3107 case '+': add
= 1; break;
3108 case '-': add
= 0; break;
3110 if (!(pos
= handle_inverse_flags
[(unsigned char)str
[nn
]])) {
3111 send_message(user
, bot
, "NSMSG_INVALID_FLAG", str
[nn
]);
3114 if (user
&& (user
->handle_info
->opserv_level
< flag_access_levels
[pos
-1])) {
3115 /* cheesy avoidance of looking up the flag name.. */
3116 send_message(user
, bot
, "NSMSG_FLAG_PRIVILEGED", str
[nn
]);
3119 flag
= 1 << (pos
- 1);
3121 added
|= flag
, removed
&= ~flag
;
3123 removed
|= flag
, added
&= ~flag
;
3128 *premoved
= removed
;
3133 nickserv_apply_flags(struct userNode
*user
, struct handle_info
*hi
, const char *flags
)
3135 unsigned long before
, after
, added
, removed
;
3136 struct userNode
*uNode
;
3138 before
= hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
);
3139 if (!nickserv_modify_handle_flags(user
, nickserv
, flags
, &added
, &removed
))
3141 hi
->flags
= (hi
->flags
| added
) & ~removed
;
3142 after
= hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
);
3144 /* Strip helping flag if they're only a support helper and not
3145 * currently in #support. */
3146 if (HANDLE_FLAGGED(hi
, HELPING
) && (after
== HI_FLAG_SUPPORT_HELPER
)) {
3147 struct channelList
*schannels
;
3149 schannels
= chanserv_support_channels();
3150 for (ii
= 0; ii
< schannels
->used
; ++ii
)
3151 if (find_handle_in_channel(schannels
->list
[ii
], hi
, NULL
))
3153 if (ii
== schannels
->used
)
3154 HANDLE_CLEAR_FLAG(hi
, HELPING
);
3157 if (after
&& !before
) {
3158 /* Add user to current helper list. */
3159 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
3160 userList_append(&curr_helpers
, uNode
);
3161 } else if (!after
&& before
) {
3162 /* Remove user from current helper list. */
3163 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
3164 userList_remove(&curr_helpers
, uNode
);
3171 set_list(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, int override
)
3175 char *set_display
[] = {
3176 "INFO", "WIDTH", "TABLEWIDTH", "COLOR", "PRIVMSG", "STYLE",
3177 "EMAIL", "ANNOUNCEMENTS", "AUTOHIDE", "MAXLOGINS", "LANGUAGE",
3178 "FAKEHOST", "TITLE", "EPITHET", "ADVANCED"
3181 reply("NSMSG_SETTING_LIST");
3182 reply("NSMSG_SETTING_LIST_HEADER");
3184 /* Do this so options are presented in a consistent order. */
3185 for (i
= 0; i
< ArrayLength(set_display
); ++i
)
3186 if ((opt
= dict_find(nickserv_opt_dict
, set_display
[i
], NULL
)))
3187 opt(cmd
, user
, hi
, override
, 0, 0, NULL
);
3188 reply("NSMSG_SETTING_LIST_END");
3191 static NICKSERV_FUNC(cmd_set
)
3193 struct handle_info
*hi
;
3196 hi
= user
->handle_info
;
3198 set_list(cmd
, user
, hi
, 0);
3201 if (!(opt
= dict_find(nickserv_opt_dict
, argv
[1], NULL
))) {
3202 reply("NSMSG_INVALID_OPTION", argv
[1]);
3205 return opt(cmd
, user
, hi
, 0, 0, argc
-1, argv
+1);
3208 static NICKSERV_FUNC(cmd_oset
)
3210 struct handle_info
*hi
;
3213 NICKSERV_MIN_PARMS(2);
3215 if (!(hi
= get_victim_oper(user
, argv
[1])))
3219 set_list(cmd
, user
, hi
, 0);
3223 if (!(opt
= dict_find(nickserv_opt_dict
, argv
[2], NULL
))) {
3224 reply("NSMSG_INVALID_OPTION", argv
[2]);
3228 return opt(cmd
, user
, hi
, 1, 0, argc
-2, argv
+2);
3231 static OPTION_FUNC(opt_info
)
3235 if ((argv
[1][0] == '*') && (argv
[1][1] == 0)) {
3237 hi
->infoline
= NULL
;
3239 hi
->infoline
= strdup(unsplit_string(argv
+1, argc
-1, NULL
));
3243 info
= hi
->infoline
? hi
->infoline
: user_find_message(user
, "MSG_NONE");
3245 reply("NSMSG_SET_INFO", info
);
3249 static OPTION_FUNC(opt_width
)
3252 hi
->screen_width
= strtoul(argv
[1], NULL
, 0);
3254 if ((hi
->screen_width
> 0) && (hi
->screen_width
< MIN_LINE_SIZE
))
3255 hi
->screen_width
= MIN_LINE_SIZE
;
3256 else if (hi
->screen_width
> MAX_LINE_SIZE
)
3257 hi
->screen_width
= MAX_LINE_SIZE
;
3260 reply("NSMSG_SET_WIDTH", hi
->screen_width
);
3264 static OPTION_FUNC(opt_tablewidth
)
3267 hi
->table_width
= strtoul(argv
[1], NULL
, 0);
3269 if ((hi
->table_width
> 0) && (hi
->table_width
< MIN_LINE_SIZE
))
3270 hi
->table_width
= MIN_LINE_SIZE
;
3271 else if (hi
->screen_width
> MAX_LINE_SIZE
)
3272 hi
->table_width
= MAX_LINE_SIZE
;
3275 reply("NSMSG_SET_TABLEWIDTH", hi
->table_width
);
3279 static OPTION_FUNC(opt_color
)
3282 if (enabled_string(argv
[1]))
3283 HANDLE_SET_FLAG(hi
, MIRC_COLOR
);
3284 else if (disabled_string(argv
[1]))
3285 HANDLE_CLEAR_FLAG(hi
, MIRC_COLOR
);
3288 reply("MSG_INVALID_BINARY", argv
[1]);
3294 reply("NSMSG_SET_COLOR", user_find_message(user
, HANDLE_FLAGGED(hi
, MIRC_COLOR
) ? "MSG_ON" : "MSG_OFF"));
3298 static OPTION_FUNC(opt_privmsg
)
3301 if (enabled_string(argv
[1]))
3302 HANDLE_SET_FLAG(hi
, USE_PRIVMSG
);
3303 else if (disabled_string(argv
[1]))
3304 HANDLE_CLEAR_FLAG(hi
, USE_PRIVMSG
);
3307 reply("MSG_INVALID_BINARY", argv
[1]);
3313 reply("NSMSG_SET_PRIVMSG", user_find_message(user
, HANDLE_FLAGGED(hi
, USE_PRIVMSG
) ? "MSG_ON" : "MSG_OFF"));
3317 static OPTION_FUNC(opt_autohide
)
3320 if (enabled_string(argv
[1]))
3321 HANDLE_SET_FLAG(hi
, AUTOHIDE
);
3322 else if (disabled_string(argv
[1]))
3323 HANDLE_CLEAR_FLAG(hi
, AUTOHIDE
);
3326 reply("MSG_INVALID_BINARY", argv
[1]);
3332 reply("NSMSG_SET_AUTOHIDE", user_find_message(user
, HANDLE_FLAGGED(hi
, AUTOHIDE
) ? "MSG_ON" : "MSG_OFF"));
3336 static OPTION_FUNC(opt_style
)
3341 if (!irccasecmp(argv
[1], "Clean"))
3342 hi
->userlist_style
= HI_STYLE_CLEAN
;
3343 else if (!irccasecmp(argv
[1], "Advanced"))
3344 hi
->userlist_style
= HI_STYLE_ADVANCED
;
3345 else if (!irccasecmp(argv
[1], "Classic"))
3346 hi
->userlist_style
= HI_STYLE_CLASSIC
;
3347 else /* Default to normal */
3348 hi
->userlist_style
= HI_STYLE_NORMAL
;
3349 } /* TODO: give error if unknow style is chosen */
3351 switch (hi
->userlist_style
) {
3352 case HI_STYLE_ADVANCED
:
3355 case HI_STYLE_CLASSIC
:
3358 case HI_STYLE_CLEAN
:
3361 case HI_STYLE_NORMAL
:
3367 reply("NSMSG_SET_STYLE", style
);
3371 static OPTION_FUNC(opt_announcements
)
3376 if (enabled_string(argv
[1]))
3377 hi
->announcements
= 'y';
3378 else if (disabled_string(argv
[1]))
3379 hi
->announcements
= 'n';
3380 else if (!strcmp(argv
[1], "?") || !irccasecmp(argv
[1], "default"))
3381 hi
->announcements
= '?';
3384 reply("NSMSG_INVALID_ANNOUNCE", argv
[1]);
3389 switch (hi
->announcements
) {
3390 case 'y': choice
= user_find_message(user
, "MSG_ON"); break;
3391 case 'n': choice
= user_find_message(user
, "MSG_OFF"); break;
3392 case '?': choice
= "default"; break;
3393 default: choice
= "unknown"; break;
3396 reply("NSMSG_SET_ANNOUNCEMENTS", choice
);
3400 static OPTION_FUNC(opt_password
)
3402 char crypted
[MD5_CRYPT_LENGTH
+1];
3408 reply("NSMSG_USE_CMD_PASS");
3412 cryptpass(argv
[1], crypted
);
3414 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
3416 if((rc
= ldap_do_modify(hi
->handle
, crypted
, NULL
)) != LDAP_SUCCESS
) {
3418 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3423 strcpy(hi
->passwd
, crypted
);
3424 if (nickserv_conf
.sync_log
)
3425 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
3428 reply("NSMSG_SET_PASSWORD", "***");
3432 static OPTION_FUNC(opt_flags
)
3435 unsigned int ii
, flen
;
3439 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3444 nickserv_apply_flags(user
, hi
, argv
[1]);
3446 for (ii
= flen
= 0; handle_flags
[ii
]; ii
++)
3447 if (hi
->flags
& (1 << ii
))
3448 flags
[flen
++] = handle_flags
[ii
];
3452 reply("NSMSG_SET_FLAGS", flags
);
3454 reply("NSMSG_SET_FLAGS", user_find_message(user
, "MSG_NONE"));
3459 static OPTION_FUNC(opt_email
)
3463 if (!valid_email(argv
[1])) {
3465 reply("NSMSG_BAD_EMAIL_ADDR");
3468 if ((str
= mail_prohibited_address(argv
[1]))) {
3470 reply("NSMSG_EMAIL_PROHIBITED", argv
[1], str
);
3473 if (hi
->email_addr
&& !irccasecmp(hi
->email_addr
, argv
[1])) {
3475 reply("NSMSG_EMAIL_SAME");
3476 } else if (!override
)
3477 nickserv_make_cookie(user
, hi
, EMAIL_CHANGE
, argv
[1], 0);
3480 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
3482 if((rc
= ldap_do_modify(hi
->handle
, NULL
, argv
[1])) != LDAP_SUCCESS
) {
3484 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3489 nickserv_set_email_addr(hi
, argv
[1]);
3491 nickserv_eat_cookie(hi
->cookie
);
3493 reply("NSMSG_SET_EMAIL", visible_email_addr(user
, hi
));
3497 reply("NSMSG_SET_EMAIL", visible_email_addr(user
, hi
));
3502 static OPTION_FUNC(opt_maxlogins
)
3504 unsigned char maxlogins
;
3506 maxlogins
= strtoul(argv
[1], NULL
, 0);
3507 if ((maxlogins
> nickserv_conf
.hard_maxlogins
) && !override
) {
3509 reply("NSMSG_BAD_MAX_LOGINS", nickserv_conf
.hard_maxlogins
);
3512 hi
->maxlogins
= maxlogins
;
3514 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
3516 reply("NSMSG_SET_MAXLOGINS", maxlogins
);
3520 static OPTION_FUNC(opt_advanced
)
3523 if (enabled_string(argv
[1]))
3524 HANDLE_SET_FLAG(hi
, ADVANCED
);
3525 else if (disabled_string(argv
[1]))
3526 HANDLE_CLEAR_FLAG(hi
, ADVANCED
);
3529 reply("MSG_INVALID_BINARY", argv
[1]);
3535 reply("NSMSG_SET_ADVANCED", user_find_message(user
, HANDLE_FLAGGED(hi
, ADVANCED
) ? "MSG_ON" : "MSG_OFF"));
3539 static OPTION_FUNC(opt_language
)
3541 struct language
*lang
;
3543 lang
= language_find(argv
[1]);
3544 if (irccasecmp(lang
->name
, argv
[1])) {
3546 reply("NSMSG_LANGUAGE_NOT_FOUND", argv
[1], lang
->name
);
3548 hi
->language
= lang
;
3551 reply("NSMSG_SET_LANGUAGE", hi
->language
->name
);
3555 static OPTION_FUNC(opt_karma
)
3559 send_message(user
, nickserv
, "MSG_SETTING_PRIVILEGED", argv
[0]);
3564 if (argv
[1][0] == '+' && isdigit(argv
[1][1])) {
3565 hi
->karma
+= strtoul(argv
[1] + 1, NULL
, 10);
3566 } else if (argv
[1][0] == '-' && isdigit(argv
[1][1])) {
3567 hi
->karma
-= strtoul(argv
[1] + 1, NULL
, 10);
3570 send_message(user
, nickserv
, "NSMSG_INVALID_KARMA", argv
[1]);
3575 send_message(user
, nickserv
, "NSMSG_SET_KARMA", hi
->karma
);
3579 /* Called from opserv from cmd_access */
3581 oper_try_set_access(struct userNode
*user
, struct userNode
*bot
, struct handle_info
*target
, unsigned int new_level
) {
3582 if (!oper_has_access(user
, bot
, nickserv_conf
.modoper_level
, 0))
3584 if ((user
->handle_info
->opserv_level
< target
->opserv_level
)
3585 || ((user
->handle_info
->opserv_level
== target
->opserv_level
)
3586 && (user
->handle_info
->opserv_level
< 1000))) {
3587 send_message(user
, bot
, "MSG_USER_OUTRANKED", target
->handle
);
3590 if ((user
->handle_info
->opserv_level
< new_level
)
3591 || ((user
->handle_info
->opserv_level
== new_level
)
3592 && (user
->handle_info
->opserv_level
< 1000))) {
3593 send_message(user
, bot
, "NSMSG_OPSERV_LEVEL_BAD");
3596 if (user
->handle_info
== target
) {
3597 send_message(user
, bot
, "MSG_STUPID_ACCESS_CHANGE");
3601 if(nickserv_conf
.ldap_enable
&& *(nickserv_conf
.ldap_oper_group_dn
) && *(nickserv_conf
.ldap_admin_dn
)) {
3603 if(new_level
> nickserv_conf
.ldap_oper_group_level
)
3604 rc
= ldap_add2group(target
->handle
, nickserv_conf
.ldap_oper_group_dn
);
3606 rc
= ldap_delfromgroup(target
->handle
, nickserv_conf
.ldap_oper_group_dn
);
3607 if(rc
!= LDAP_SUCCESS
&& rc
!= LDAP_TYPE_OR_VALUE_EXISTS
&& rc
!= LDAP_NO_SUCH_ATTRIBUTE
) {
3608 send_message(user
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3612 if(nickserv_conf
.ldap_enable
&& *(nickserv_conf
.ldap_field_oslevel
) && *(nickserv_conf
.ldap_admin_dn
)) {
3614 if((rc
= ldap_do_oslevel(target
->handle
, new_level
, target
->opserv_level
)) != LDAP_SUCCESS
) {
3615 send_message(user
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3620 if (target
->opserv_level
== new_level
)
3622 log_module(NS_LOG
, LOG_INFO
, "Account %s setting oper level for account %s to %d (from %d).",
3623 user
->handle_info
->handle
, target
->handle
, new_level
, target
->opserv_level
);
3624 target
->opserv_level
= new_level
;
3628 static OPTION_FUNC(opt_level
)
3634 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3638 res
= (argc
> 1) ? oper_try_set_access(user
, nickserv
, hi
, strtoul(argv
[1], NULL
, 0)) : 0;
3640 reply("NSMSG_SET_LEVEL", hi
->opserv_level
);
3644 static OPTION_FUNC(opt_epithet
)
3646 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_epithet_level
, 0)) {
3648 struct userNode
*target
, *next_un
;
3652 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3656 epithet
= unsplit_string(argv
+1, argc
-1, NULL
);
3660 if ((epithet
[0] == '*') && !epithet
[1])
3663 hi
->epithet
= strdup(epithet
);
3665 for (target
= hi
->users
; target
; target
= next_un
) {
3666 irc_swhois(nickserv
, target
, hi
->epithet
);
3668 next_un
= target
->next_authed
;
3674 reply("NSMSG_SET_EPITHET", hi
->epithet
);
3676 reply("NSMSG_SET_EPITHET", user_find_message(user
, "MSG_NONE"));
3681 static OPTION_FUNC(opt_title
)
3684 const char *none
= NULL
;
3687 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_title_level
, 0)) {
3690 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3695 if(!strcmp(title
, "*")) {
3697 hi
->fakehost
= NULL
;
3700 if (strchr(title
, '.')) {
3702 reply("NSMSG_TITLE_INVALID");
3705 /* Alphanumeric titles only. */
3706 for(sptr
= title
; *sptr
; sptr
++) {
3707 if(!isalnum(*sptr
) && *sptr
!= '-') {
3709 reply("NSMSG_TITLE_INVALID");
3713 if ((strlen(user
->handle_info
->handle
) + strlen(title
) +
3714 strlen(nickserv_conf
.titlehost_suffix
) + 2) > HOSTLEN
) {
3716 reply("NSMSG_TITLE_TRUNCATED");
3720 hi
->fakehost
= malloc(strlen(title
)+2);
3721 hi
->fakehost
[0] = '.';
3722 strcpy(hi
->fakehost
+1, title
);
3725 } else if (hi
->fakehost
&& (hi
->fakehost
[0] == '.'))
3726 title
= hi
->fakehost
+ 1;
3728 /* If theres no title set then the default title will therefore
3729 be the first part of hidden_host in x3.conf, so for
3730 consistency with opt_fakehost we will print this here.
3731 This isnt actually used in P10, its just handled to keep from crashing... */
3732 char *hs
, *hidden_suffix
, *rest
;
3734 hs
= conf_get_data("server/hidden_host", RECDB_QSTRING
);
3735 hidden_suffix
= strdup(hs
);
3737 /* Yes we do this twice */
3738 if((rest
= strchr(hidden_suffix
, '.')))
3741 title
= hidden_suffix
;
3745 /* A lame default if someone configured hidden_host to something lame */
3746 title
= strdup("users");
3747 free(hidden_suffix
);
3753 none
= user_find_message(user
, "MSG_NONE");
3755 send_message(user
, nickserv
, "NSMSG_SET_TITLE", title
? title
: none
);
3760 check_vhost(char *vhost
, struct userNode
*user
, struct svccmd
*cmd
)
3764 // check for a dot in the vhost
3765 if(strchr(vhost
, '.') == NULL
) {
3766 reply("NSMSG_NOT_VALID_FAKEHOST_DOT", vhost
);
3770 // check for a @ in the vhost
3771 if(strchr(vhost
, '@') != NULL
) {
3772 reply("NSMSG_NOT_VALID_FAKEHOST_AT", vhost
);
3776 // check for denied words, inspired by monk at paki.sex
3777 for(y
= 0; y
< nickserv_conf
.denied_fakehost_words
->used
; y
++) {
3778 if(strstr(vhost
, nickserv_conf
.denied_fakehost_words
->list
[y
]) != NULL
) {
3779 reply("NSMSG_DENIED_FAKEHOST_WORD", vhost
, nickserv_conf
.denied_fakehost_words
->list
[y
]);
3784 // check for ircu's HOSTLEN length.
3785 if(strlen(vhost
) >= HOSTLEN
) {
3786 reply("NSMSG_NOT_VALID_FAKEHOST_LEN", vhost
);
3790 /* This can be handled by the regex now if desired.
3791 if (vhost[strspn(vhost, "0123456789.")]) {
3792 hostname = vhost + strlen(vhost);
3793 for (depth = 1; depth && (hostname > vhost); depth--) {
3795 while ((hostname > vhost) && (*hostname != '.')) hostname--;
3798 if (*hostname == '.') hostname++; * advance past last dot we saw *
3799 if(strlen(hostname) > 4) {
3800 reply("NSMSG_NOT_VALID_FAKEHOST_TLD_LEN", vhost);
3805 /* test either regex or as valid handle */
3806 if (nickserv_conf
.valid_fakehost_regex_set
) {
3807 int err
= regexec(&nickserv_conf
.valid_fakehost_regex
, vhost
, 0, 0, 0);
3810 buff
[regerror(err
, &nickserv_conf
.valid_fakehost_regex
, buff
, sizeof(buff
))] = 0;
3811 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
3813 if(err
== REG_NOMATCH
) {
3814 reply("NSMSG_NOT_VALID_FAKEHOST_REGEX", vhost
);
3823 static OPTION_FUNC(opt_fakehost
)
3827 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_fakehost_level
, 0)) {
3830 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3835 if ((strlen(fake
) > HOSTLEN
) || (fake
[0] == '.')) {
3837 reply("NSMSG_FAKEHOST_INVALID", HOSTLEN
);
3840 if (!strcmp(fake
, "*")) {
3843 hi
->fakehost
= NULL
;
3846 else if (!check_vhost(argv
[1], user
, cmd
)) {
3847 /* check_vhost takes care of error reply */
3853 hi
->fakehost
= strdup(fake
);
3856 fake
= hi
->fakehost
;
3858 fake
= generate_fakehost(hi
);
3860 /* Tell them we set the host */
3862 fake
= user_find_message(user
, "MSG_NONE");
3864 reply("NSMSG_SET_FAKEHOST", fake
);
3868 static OPTION_FUNC(opt_note
)
3872 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3877 char *text
= unsplit_string(argv
+ 1, argc
- 1, NULL
);
3882 if ((text
[0] == '*') && !text
[1])
3885 if (!(hi
->note
= nickserv_add_note(user
->handle_info
->handle
, now
, text
)))
3891 reply("NSMSG_SET_NOTE", hi
->note
? hi
->note
->note
: user_find_message(user
, "MSG_NONE"));
3895 static NICKSERV_FUNC(cmd_reclaim
)
3897 struct handle_info
*hi
;
3898 struct nick_info
*ni
;
3899 struct userNode
*victim
;
3901 NICKSERV_MIN_PARMS(2);
3902 hi
= user
->handle_info
;
3903 ni
= dict_find(nickserv_nick_dict
, argv
[1], 0);
3905 reply("NSMSG_UNKNOWN_NICK", argv
[1]);
3908 if (ni
->owner
!= user
->handle_info
) {
3909 reply("NSMSG_NOT_YOUR_NICK", ni
->nick
);
3912 victim
= GetUserH(ni
->nick
);
3914 reply("MSG_NICK_UNKNOWN", ni
->nick
);
3917 if (victim
== user
) {
3918 reply("NSMSG_NICK_USER_YOU");
3921 nickserv_reclaim(victim
, ni
, nickserv_conf
.reclaim_action
);
3922 switch (nickserv_conf
.reclaim_action
) {
3923 case RECLAIM_NONE
: reply("NSMSG_RECLAIMED_NONE"); break;
3924 case RECLAIM_WARN
: reply("NSMSG_RECLAIMED_WARN", victim
->nick
); break;
3925 case RECLAIM_SVSNICK
: reply("NSMSG_RECLAIMED_SVSNICK", victim
->nick
); break;
3926 case RECLAIM_KILL
: reply("NSMSG_RECLAIMED_KILL", victim
->nick
); break;
3931 static NICKSERV_FUNC(cmd_unregnick
)
3934 struct handle_info
*hi
;
3935 struct nick_info
*ni
;
3937 hi
= user
->handle_info
;
3938 nick
= (argc
< 2) ? user
->nick
: (const char*)argv
[1];
3939 ni
= dict_find(nickserv_nick_dict
, nick
, NULL
);
3941 reply("NSMSG_UNKNOWN_NICK", nick
);
3944 if (hi
!= ni
->owner
) {
3945 reply("NSMSG_NOT_YOUR_NICK", nick
);
3948 reply("NSMSG_UNREGNICK_SUCCESS", ni
->nick
);
3953 static NICKSERV_FUNC(cmd_ounregnick
)
3955 struct nick_info
*ni
;
3957 NICKSERV_MIN_PARMS(2);
3958 if (!(ni
= get_nick_info(argv
[1]))) {
3959 reply("NSMSG_NICK_NOT_REGISTERED", argv
[1]);
3962 if (!oper_outranks(user
, ni
->owner
))
3964 reply("NSMSG_UNREGNICK_SUCCESS", ni
->nick
);
3969 static NICKSERV_FUNC(cmd_unregister
)
3971 struct handle_info
*hi
;
3974 NICKSERV_MIN_PARMS(2);
3975 hi
= user
->handle_info
;
3978 if (checkpass(passwd
, hi
->passwd
)) {
3979 if(nickserv_unregister_handle(hi
, user
, cmd
->parent
->bot
))
3984 log_module(NS_LOG
, LOG_INFO
, "Account '%s' tried to unregister with the wrong password.", hi
->handle
);
3985 reply("NSMSG_PASSWORD_INVALID");
3990 static NICKSERV_FUNC(cmd_ounregister
)
3992 struct handle_info
*hi
;
3993 char reason
[MAXLEN
];
3996 NICKSERV_MIN_PARMS(2);
3997 if (!(hi
= get_victim_oper(user
, argv
[1])))
4000 if (HANDLE_FLAGGED(hi
, NODELETE
)) {
4001 reply("NSMSG_UNREGISTER_NODELETE", hi
->handle
);
4005 force
= IsOper(user
) && (argc
> 2) && !irccasecmp(argv
[2], "force");
4007 ((hi
->flags
& nickserv_conf
.ounregister_flags
)
4009 || (hi
->last_quit_host
[0] && ((unsigned)(now
- hi
->lastseen
) < nickserv_conf
.ounregister_inactive
)))) {
4010 reply((IsOper(user
) ? "NSMSG_UNREGISTER_MUST_FORCE" : "NSMSG_UNREGISTER_CANNOT_FORCE"), hi
->handle
);
4013 snprintf(reason
, sizeof(reason
), "%s unregistered account %s.", user
->handle_info
->handle
, hi
->handle
);
4014 global_message(MESSAGE_RECIPIENT_STAFF
, reason
);
4015 if(nickserv_unregister_handle(hi
, user
, cmd
->parent
->bot
))
4021 static NICKSERV_FUNC(cmd_status
)
4023 if (nickserv_conf
.disable_nicks
) {
4024 reply("NSMSG_GLOBAL_STATS_NONICK",
4025 dict_size(nickserv_handle_dict
));
4027 if (user
->handle_info
) {
4029 struct nick_info
*ni
;
4030 for (ni
=user
->handle_info
->nicks
; ni
; ni
=ni
->next
) cnt
++;
4031 reply("NSMSG_HANDLE_STATS", cnt
);
4033 reply("NSMSG_HANDLE_NONE");
4035 reply("NSMSG_GLOBAL_STATS",
4036 dict_size(nickserv_handle_dict
),
4037 dict_size(nickserv_nick_dict
));
4042 static NICKSERV_FUNC(cmd_ghost
)
4044 struct userNode
*target
;
4045 char reason
[MAXLEN
];
4047 NICKSERV_MIN_PARMS(2);
4048 if (!(target
= GetUserH(argv
[1]))) {
4049 reply("MSG_NICK_UNKNOWN", argv
[1]);
4052 if (target
== user
) {
4053 reply("NSMSG_CANNOT_GHOST_SELF");
4056 if (!target
->handle_info
|| (target
->handle_info
!= user
->handle_info
)) {
4057 reply("NSMSG_CANNOT_GHOST_USER", target
->nick
);
4060 snprintf(reason
, sizeof(reason
), "Ghost kill on account %s (requested by %s).", target
->handle_info
->handle
, user
->nick
);
4061 DelUser(target
, nickserv
, 1, reason
);
4062 reply("NSMSG_GHOST_KILLED", argv
[1]);
4066 static NICKSERV_FUNC(cmd_vacation
)
4068 HANDLE_SET_FLAG(user
->handle_info
, FROZEN
);
4069 reply("NSMSG_ON_VACATION");
4074 nickserv_saxdb_write(struct saxdb_context
*ctx
) {
4076 struct handle_info
*hi
;
4079 for (it
= dict_first(nickserv_handle_dict
); it
; it
= iter_next(it
)) {
4081 saxdb_start_record(ctx
, iter_key(it
), 0);
4082 if (hi
->announcements
!= '?') {
4083 flags
[0] = hi
->announcements
;
4085 saxdb_write_string(ctx
, KEY_ANNOUNCEMENTS
, flags
);
4088 struct handle_cookie
*cookie
= hi
->cookie
;
4091 switch (cookie
->type
) {
4092 case ACTIVATION
: type
= KEY_ACTIVATION
; break;
4093 case PASSWORD_CHANGE
: type
= KEY_PASSWORD_CHANGE
; break;
4094 case EMAIL_CHANGE
: type
= KEY_EMAIL_CHANGE
; break;
4095 case ALLOWAUTH
: type
= KEY_ALLOWAUTH
; break;
4096 default: type
= NULL
; break;
4099 saxdb_start_record(ctx
, KEY_COOKIE
, 0);
4100 saxdb_write_string(ctx
, KEY_COOKIE_TYPE
, type
);
4101 saxdb_write_int(ctx
, KEY_COOKIE_EXPIRES
, cookie
->expires
);
4103 saxdb_write_string(ctx
, KEY_COOKIE_DATA
, cookie
->data
);
4104 saxdb_write_string(ctx
, KEY_COOKIE
, cookie
->cookie
);
4105 saxdb_end_record(ctx
);
4109 saxdb_write_string(ctx
, KEY_EMAIL_ADDR
, hi
->email_addr
);
4111 saxdb_write_string(ctx
, KEY_EPITHET
, hi
->epithet
);
4113 saxdb_start_record(ctx
, KEY_NOTE_NOTE
, 0);
4114 saxdb_write_string(ctx
, KEY_NOTE_SETTER
, hi
->note
->setter
);
4115 saxdb_write_int(ctx
, KEY_NOTE_DATE
, hi
->note
->date
);
4116 saxdb_write_string(ctx
, KEY_NOTE_NOTE
, hi
->note
->note
);
4117 saxdb_end_record(ctx
);
4121 saxdb_write_string(ctx
, KEY_FAKEHOST
, hi
->fakehost
);
4125 for (ii
=flen
=0; handle_flags
[ii
]; ++ii
)
4126 if (hi
->flags
& (1 << ii
))
4127 flags
[flen
++] = handle_flags
[ii
];
4129 saxdb_write_string(ctx
, KEY_FLAGS
, flags
);
4132 saxdb_write_string(ctx
, KEY_INFO
, hi
->infoline
);
4133 if (hi
->last_quit_host
[0])
4134 saxdb_write_string(ctx
, KEY_LAST_QUIT_HOST
, hi
->last_quit_host
);
4135 saxdb_write_int(ctx
, KEY_LAST_SEEN
, hi
->lastseen
);
4137 saxdb_write_sint(ctx
, KEY_KARMA
, hi
->karma
);
4138 if (hi
->masks
->used
)
4139 saxdb_write_string_list(ctx
, KEY_MASKS
, hi
->masks
);
4140 if (hi
->sslfps
->used
)
4141 saxdb_write_string_list(ctx
, KEY_SSLFPS
, hi
->sslfps
);
4142 if (hi
->ignores
->used
)
4143 saxdb_write_string_list(ctx
, KEY_IGNORES
, hi
->ignores
);
4145 saxdb_write_int(ctx
, KEY_MAXLOGINS
, hi
->maxlogins
);
4147 struct nick_info
*ni
;
4149 saxdb_start_record(ctx
, KEY_NICKS_EX
, 0);
4150 for (ni
= hi
->nicks
; ni
; ni
= ni
->next
) {
4151 saxdb_start_record(ctx
, ni
->nick
, 0);
4152 saxdb_write_int(ctx
, KEY_REGISTER_ON
, ni
->registered
);
4153 saxdb_write_int(ctx
, KEY_LAST_SEEN
, ni
->lastseen
);
4154 saxdb_end_record(ctx
);
4156 saxdb_end_record(ctx
);
4158 if (hi
->opserv_level
)
4159 saxdb_write_int(ctx
, KEY_OPSERV_LEVEL
, hi
->opserv_level
);
4160 if (hi
->language
!= lang_C
)
4161 saxdb_write_string(ctx
, KEY_LANGUAGE
, hi
->language
->name
);
4162 saxdb_write_string(ctx
, KEY_PASSWD
, hi
->passwd
);
4163 saxdb_write_int(ctx
, KEY_REGISTER_ON
, hi
->registered
);
4164 if (hi
->screen_width
)
4165 saxdb_write_int(ctx
, KEY_SCREEN_WIDTH
, hi
->screen_width
);
4166 if (hi
->table_width
)
4167 saxdb_write_int(ctx
, KEY_TABLE_WIDTH
, hi
->table_width
);
4168 flags
[0] = hi
->userlist_style
;
4170 saxdb_write_string(ctx
, KEY_USERLIST_STYLE
, flags
);
4171 saxdb_end_record(ctx
);
4177 static handle_merge_func_t
*handle_merge_func_list
;
4178 static void **handle_merge_func_list_extra
;
4179 static unsigned int handle_merge_func_size
= 0, handle_merge_func_used
= 0;
4182 reg_handle_merge_func(handle_merge_func_t func
, void *extra
)
4184 if (handle_merge_func_used
== handle_merge_func_size
) {
4185 if (handle_merge_func_size
) {
4186 handle_merge_func_size
<<= 1;
4187 handle_merge_func_list
= realloc(handle_merge_func_list
, handle_merge_func_size
*sizeof(handle_merge_func_t
));
4188 handle_merge_func_list_extra
= realloc(handle_merge_func_list_extra
, handle_merge_func_size
*sizeof(void*));
4190 handle_merge_func_size
= 8;
4191 handle_merge_func_list
= malloc(handle_merge_func_size
*sizeof(handle_merge_func_t
));
4192 handle_merge_func_list_extra
= malloc(handle_merge_func_size
*sizeof(void*));
4195 handle_merge_func_list
[handle_merge_func_used
] = func
;
4196 handle_merge_func_list_extra
[handle_merge_func_used
++] = extra
;
4199 static NICKSERV_FUNC(cmd_merge
)
4201 struct handle_info
*hi_from
, *hi_to
;
4202 struct userNode
*last_user
;
4203 struct userData
*cList
, *cListNext
;
4204 unsigned int ii
, jj
, n
;
4206 NICKSERV_MIN_PARMS(3);
4208 if (!(hi_from
= get_victim_oper(user
, argv
[1])))
4210 if (!(hi_to
= get_victim_oper(user
, argv
[2])))
4212 if (hi_to
== hi_from
) {
4213 reply("NSMSG_CANNOT_MERGE_SELF", hi_to
->handle
);
4217 for (n
=0; n
<handle_merge_func_used
; n
++)
4218 handle_merge_func_list
[n
](user
, hi_to
, hi_from
, handle_merge_func_list_extra
[n
]);
4220 /* Append "from" handle's nicks to "to" handle's nick list. */
4222 struct nick_info
*last_ni
;
4223 for (last_ni
=hi_to
->nicks
; last_ni
->next
; last_ni
=last_ni
->next
) ;
4224 last_ni
->next
= hi_from
->nicks
;
4226 while (hi_from
->nicks
) {
4227 hi_from
->nicks
->owner
= hi_to
;
4228 hi_from
->nicks
= hi_from
->nicks
->next
;
4231 /* Merge the hostmasks. */
4232 for (ii
=0; ii
<hi_from
->masks
->used
; ii
++) {
4233 char *mask
= hi_from
->masks
->list
[ii
];
4234 for (jj
=0; jj
<hi_to
->masks
->used
; jj
++)
4235 if (match_ircglobs(hi_to
->masks
->list
[jj
], mask
))
4237 if (jj
==hi_to
->masks
->used
) /* Nothing from the "to" handle covered this mask, so add it. */
4238 string_list_append(hi_to
->masks
, strdup(mask
));
4241 /* Merge the SSL fingerprints. */
4242 for (ii
=0; ii
<hi_from
->sslfps
->used
; ii
++) {
4243 char *sslfp
= hi_from
->sslfps
->list
[ii
];
4244 for (jj
=0; jj
<hi_to
->sslfps
->used
; jj
++)
4245 if (!irccasecmp(hi_to
->sslfps
->list
[jj
], sslfp
))
4247 if (jj
==hi_to
->sslfps
->used
) /* Nothing from the "to" handle covered this sslfp, so add it. */
4248 string_list_append(hi_to
->sslfps
, strdup(sslfp
));
4251 /* Merge the ignores. */
4252 for (ii
=0; ii
<hi_from
->ignores
->used
; ii
++) {
4253 char *ignore
= hi_from
->ignores
->list
[ii
];
4254 for (jj
=0; jj
<hi_to
->ignores
->used
; jj
++)
4255 if (match_ircglobs(hi_to
->ignores
->list
[jj
], ignore
))
4257 if (jj
==hi_to
->ignores
->used
) /* Nothing from the "to" handle covered this mask, so add it. */
4258 string_list_append(hi_to
->ignores
, strdup(ignore
));
4261 /* Merge the lists of authed users. */
4263 for (last_user
=hi_to
->users
; last_user
->next_authed
; last_user
=last_user
->next_authed
) ;
4264 last_user
->next_authed
= hi_from
->users
;
4266 hi_to
->users
= hi_from
->users
;
4268 /* Repoint the old "from" handle's users. */
4269 for (last_user
=hi_from
->users
; last_user
; last_user
=last_user
->next_authed
) {
4270 last_user
->handle_info
= hi_to
;
4272 hi_from
->users
= NULL
;
4274 /* Merge channel userlists. */
4275 for (cList
=hi_from
->channels
; cList
; cList
=cListNext
) {
4276 struct userData
*cList2
;
4277 cListNext
= cList
->u_next
;
4278 for (cList2
=hi_to
->channels
; cList2
; cList2
=cList2
->u_next
)
4279 if (cList
->channel
== cList2
->channel
)
4281 if (cList2
&& (cList2
->access
>= cList
->access
)) {
4282 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
);
4283 /* keep cList2 in hi_to; remove cList from hi_from */
4284 del_channel_user(cList
, 1);
4287 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
);
4288 /* remove the lower-ranking cList2 from hi_to */
4289 del_channel_user(cList2
, 1);
4291 log_module(NS_LOG
, LOG_INFO
, "Merge: %s had no access in %s", hi_to
->handle
, cList
->channel
->channel
->name
);
4293 /* cList needs to be moved from hi_from to hi_to */
4294 cList
->handle
= hi_to
;
4295 /* Remove from linked list for hi_from */
4296 assert(!cList
->u_prev
);
4297 hi_from
->channels
= cList
->u_next
;
4299 cList
->u_next
->u_prev
= cList
->u_prev
;
4300 /* Add to linked list for hi_to */
4301 cList
->u_prev
= NULL
;
4302 cList
->u_next
= hi_to
->channels
;
4303 if (hi_to
->channels
)
4304 hi_to
->channels
->u_prev
= cList
;
4305 hi_to
->channels
= cList
;
4309 /* Do they get an OpServ level promotion? */
4310 if (hi_from
->opserv_level
> hi_to
->opserv_level
)
4311 hi_to
->opserv_level
= hi_from
->opserv_level
;
4313 /* What about last seen time? */
4314 if (hi_from
->lastseen
> hi_to
->lastseen
)
4315 hi_to
->lastseen
= hi_from
->lastseen
;
4317 /* New karma is the sum of the two original karmas. */
4318 hi_to
->karma
+= hi_from
->karma
;
4320 /* Does a fakehost carry over? (This intentionally doesn't set it
4321 * for users previously attached to hi_to. They'll just have to
4324 if (hi_from
->fakehost
&& !hi_to
->fakehost
)
4325 hi_to
->fakehost
= strdup(hi_from
->fakehost
);
4327 /* Notify of success. */
4328 reply("NSMSG_HANDLES_MERGED", hi_from
->handle
, hi_to
->handle
);
4329 global_message_args(MESSAGE_RECIPIENT_OPERS
, "NSMSG_ACCOUNT_MERGED", user
->nick
,
4330 user
->handle_info
->handle
, hi_from
->handle
, hi_to
->handle
);
4332 /* Unregister the "from" handle. */
4333 nickserv_unregister_handle(hi_from
, NULL
, cmd
->parent
->bot
);
4334 /* TODO: fix it so that if the ldap delete in nickserv_unregister_handle fails,
4335 * the process isn't completed.
4341 struct nickserv_discrim
{
4342 unsigned long flags_on
, flags_off
;
4343 time_t min_registered
, max_registered
;
4346 int min_level
, max_level
;
4347 int min_karma
, max_karma
;
4348 enum { SUBSET
, EXACT
, SUPERSET
, LASTQUIT
} hostmask_type
;
4349 const char *nickmask
;
4350 const char *hostmask
;
4351 const char *handlemask
;
4352 const char *emailmask
;
4353 const char *titlemask
;
4354 const char *setwhat
;
4358 unsigned int inldap
;
4362 typedef void (*discrim_search_func
)(struct userNode
*source
, struct handle_info
*hi
, struct nickserv_discrim
*discrim
);
4364 struct discrim_apply_info
{
4365 struct nickserv_discrim
*discrim
;
4366 discrim_search_func func
;
4367 struct userNode
*source
;
4368 unsigned int matched
;
4371 static struct nickserv_discrim
*
4372 nickserv_discrim_create(struct svccmd
*cmd
, struct userNode
*user
, unsigned int argc
, char *argv
[])
4375 struct nickserv_discrim
*discrim
;
4377 discrim
= malloc(sizeof(*discrim
));
4378 memset(discrim
, 0, sizeof(*discrim
));
4379 discrim
->min_level
= 0;
4380 discrim
->max_level
= INT_MAX
;
4381 discrim
->limit
= 50;
4382 discrim
->min_registered
= 0;
4383 discrim
->max_registered
= INT_MAX
;
4384 discrim
->lastseen
= LONG_MAX
;
4385 discrim
->min_karma
= INT_MIN
;
4386 discrim
->max_karma
= INT_MAX
;
4389 discrim
->inldap
= 2;
4392 for (i
=0; i
<argc
; i
++) {
4393 if (i
== argc
- 1) {
4394 reply("MSG_MISSING_PARAMS", argv
[i
]);
4397 if (!irccasecmp(argv
[i
], "limit")) {
4398 discrim
->limit
= strtoul(argv
[++i
], NULL
, 0);
4399 } else if (!irccasecmp(argv
[i
], "flags")) {
4400 nickserv_modify_handle_flags(user
, nickserv
, argv
[++i
], &discrim
->flags_on
, &discrim
->flags_off
);
4401 } else if (!irccasecmp(argv
[i
], "registered")) {
4402 const char *cmp
= argv
[++i
];
4403 if (cmp
[0] == '<') {
4404 if (cmp
[1] == '=') {
4405 discrim
->min_registered
= now
- ParseInterval(cmp
+2);
4407 discrim
->min_registered
= now
- ParseInterval(cmp
+1) + 1;
4409 } else if (cmp
[0] == '=') {
4410 discrim
->min_registered
= discrim
->max_registered
= now
- ParseInterval(cmp
+1);
4411 } else if (cmp
[0] == '>') {
4412 if (cmp
[1] == '=') {
4413 discrim
->max_registered
= now
- ParseInterval(cmp
+2);
4415 discrim
->max_registered
= now
- ParseInterval(cmp
+1) - 1;
4418 reply("MSG_INVALID_CRITERIA", cmp
);
4420 } else if (!irccasecmp(argv
[i
], "seen")) {
4421 discrim
->lastseen
= now
- ParseInterval(argv
[++i
]);
4422 } else if (!nickserv_conf
.disable_nicks
&& !irccasecmp(argv
[i
], "nickmask")) {
4423 discrim
->nickmask
= argv
[++i
];
4424 } else if (!irccasecmp(argv
[i
], "setwhat")) {
4425 discrim
->setwhat
= argv
[++i
];
4426 if (!(dict_find(nickserv_opt_dict
, discrim
->setwhat
, NULL
))) {
4427 reply("NSMSG_INVALID_OPTION", discrim
->setwhat
);
4430 } else if (!irccasecmp(argv
[i
], "setvalue")) {
4431 discrim
->setval
= argv
[++i
];
4432 } else if (!irccasecmp(argv
[i
], "hostmask")) {
4434 if (!irccasecmp(argv
[i
], "exact")) {
4435 if (i
== argc
- 1) {
4436 reply("MSG_MISSING_PARAMS", argv
[i
]);
4439 discrim
->hostmask_type
= EXACT
;
4440 } else if (!irccasecmp(argv
[i
], "subset")) {
4441 if (i
== argc
- 1) {
4442 reply("MSG_MISSING_PARAMS", argv
[i
]);
4445 discrim
->hostmask_type
= SUBSET
;
4446 } else if (!irccasecmp(argv
[i
], "superset")) {
4447 if (i
== argc
- 1) {
4448 reply("MSG_MISSING_PARAMS", argv
[i
]);
4451 discrim
->hostmask_type
= SUPERSET
;
4452 } else if (!irccasecmp(argv
[i
], "lastquit") || !irccasecmp(argv
[i
], "lastauth")) {
4453 if (i
== argc
- 1) {
4454 reply("MSG_MISSING_PARAMS", argv
[i
]);
4457 discrim
->hostmask_type
= LASTQUIT
;
4460 discrim
->hostmask_type
= SUPERSET
;
4462 discrim
->hostmask
= argv
[++i
];
4463 } else if (!irccasecmp(argv
[i
], "handlemask") || !irccasecmp(argv
[i
], "accountmask") || !irccasecmp(argv
[i
], "account")) {
4464 if (!irccasecmp(argv
[++i
], "*")) {
4465 discrim
->handlemask
= 0;
4467 discrim
->handlemask
= argv
[i
];
4469 } else if (!irccasecmp(argv
[i
], "email")) {
4470 if (user
->handle_info
->opserv_level
< nickserv_conf
.email_search_level
) {
4471 reply("MSG_NO_SEARCH_ACCESS", "email");
4473 } else if (!irccasecmp(argv
[++i
], "*")) {
4474 discrim
->emailmask
= 0;
4476 discrim
->emailmask
= argv
[i
];
4478 } else if (!irccasecmp(argv
[i
], "title")) {
4479 if (!irccasecmp(argv
[++i
], "*")) {
4480 discrim
->titlemask
= 0;
4482 discrim
->titlemask
= argv
[i
];
4484 } else if (!irccasecmp(argv
[i
], "access")) {
4485 const char *cmp
= argv
[++i
];
4486 if (cmp
[0] == '<') {
4487 if (discrim
->min_level
== 0) discrim
->min_level
= 1;
4488 if (cmp
[1] == '=') {
4489 discrim
->max_level
= strtoul(cmp
+2, NULL
, 0);
4491 discrim
->max_level
= strtoul(cmp
+1, NULL
, 0) - 1;
4493 } else if (cmp
[0] == '=') {
4494 discrim
->min_level
= discrim
->max_level
= strtoul(cmp
+1, NULL
, 0);
4495 } else if (cmp
[0] == '>') {
4496 if (cmp
[1] == '=') {
4497 discrim
->min_level
= strtoul(cmp
+2, NULL
, 0);
4499 discrim
->min_level
= strtoul(cmp
+1, NULL
, 0) + 1;
4502 reply("MSG_INVALID_CRITERIA", cmp
);
4504 } else if (!irccasecmp(argv
[i
], "karma")) {
4505 const char *cmp
= argv
[++i
];
4506 if (cmp
[0] == '<') {
4507 if (cmp
[1] == '=') {
4508 discrim
->max_karma
= strtoul(cmp
+2, NULL
, 0);
4510 discrim
->max_karma
= strtoul(cmp
+1, NULL
, 0) - 1;
4512 } else if (cmp
[0] == '=') {
4513 discrim
->min_karma
= discrim
->max_karma
= strtoul(cmp
+1, NULL
, 0);
4514 } else if (cmp
[0] == '>') {
4515 if (cmp
[1] == '=') {
4516 discrim
->min_karma
= strtoul(cmp
+2, NULL
, 0);
4518 discrim
->min_karma
= strtoul(cmp
+1, NULL
, 0) + 1;
4521 send_message(user
, nickserv
, "MSG_INVALID_CRITERIA", cmp
);
4524 } else if (nickserv_conf
.ldap_enable
&& !irccasecmp(argv
[i
], "inldap")) {
4526 if(true_string(argv
[i
])) {
4527 discrim
->inldap
= 1;
4529 else if (false_string(argv
[i
])) {
4530 discrim
->inldap
= 0;
4533 reply("MSG_INVALID_BINARY", argv
[i
]);
4537 reply("MSG_INVALID_CRITERIA", argv
[i
]);
4548 nickserv_discrim_match(struct nickserv_discrim
*discrim
, struct handle_info
*hi
)
4552 if (hi
->fakehost
&& (hi
->fakehost
[0] == '.'))
4553 title
= hi
->fakehost
+ 1;
4555 if (((discrim
->flags_on
& hi
->flags
) != discrim
->flags_on
)
4556 || (discrim
->flags_off
& hi
->flags
)
4557 || (discrim
->min_registered
> hi
->registered
)
4558 || (discrim
->max_registered
< hi
->registered
)
4559 || (discrim
->lastseen
< (hi
->users
?now
:hi
->lastseen
))
4560 || (discrim
->handlemask
&& !match_ircglob(hi
->handle
, discrim
->handlemask
))
4561 || (discrim
->emailmask
&& (!hi
->email_addr
|| !match_ircglob(hi
->email_addr
, discrim
->emailmask
)))
4562 || (discrim
->titlemask
&& (!title
|| !match_ircglob(title
, discrim
->titlemask
)))
4563 || (discrim
->min_level
> hi
->opserv_level
)
4564 || (discrim
->max_level
< hi
->opserv_level
)
4565 || (discrim
->min_karma
> hi
->karma
)
4566 || (discrim
->max_karma
< hi
->karma
)
4570 if (discrim
->hostmask
) {
4572 for (i
=0; i
<hi
->masks
->used
; i
++) {
4573 const char *mask
= hi
->masks
->list
[i
];
4574 if ((discrim
->hostmask_type
== SUBSET
)
4575 && (match_ircglobs(discrim
->hostmask
, mask
))) break;
4576 else if ((discrim
->hostmask_type
== EXACT
)
4577 && !irccasecmp(discrim
->hostmask
, mask
)) break;
4578 else if ((discrim
->hostmask_type
== SUPERSET
)
4579 && (match_ircglobs(mask
, discrim
->hostmask
))) break;
4580 else if ((discrim
->hostmask_type
== LASTQUIT
)
4581 && (match_ircglobs(discrim
->hostmask
, hi
->last_quit_host
))) break;
4583 if (i
==hi
->masks
->used
) return 0;
4585 if (discrim
->nickmask
) {
4586 struct nick_info
*nick
= hi
->nicks
;
4588 if (match_ircglob(nick
->nick
, discrim
->nickmask
)) break;
4591 if (!nick
) return 0;
4594 if(nickserv_conf
.ldap_enable
&& discrim
->inldap
!= 2) {
4596 rc
= ldap_get_user_info(hi
->handle
, NULL
);
4597 if(discrim
->inldap
== 1 && rc
!= LDAP_SUCCESS
)
4599 if(discrim
->inldap
== 0 && rc
== LDAP_SUCCESS
)
4608 nickserv_discrim_search(struct nickserv_discrim
*discrim
, discrim_search_func dsf
, struct userNode
*source
)
4610 dict_iterator_t it
, next
;
4611 unsigned int matched
;
4613 for (it
= dict_first(nickserv_handle_dict
), matched
= 0;
4614 it
&& (matched
< discrim
->limit
);
4616 next
= iter_next(it
);
4617 if (nickserv_discrim_match(discrim
, iter_data(it
))) {
4618 dsf(source
, iter_data(it
), discrim
);
4626 search_print_func(struct userNode
*source
, struct handle_info
*match
, UNUSED_ARG(struct nickserv_discrim
*discrim
))
4628 send_message(source
, nickserv
, "NSMSG_SEARCH_MATCH", match
->handle
);
4632 search_count_func(UNUSED_ARG(struct userNode
*source
), UNUSED_ARG(struct handle_info
*match
), UNUSED_ARG(struct nickserv_discrim
*discrim
))
4637 search_unregister_func (struct userNode
*source
, struct handle_info
*match
, UNUSED_ARG(struct nickserv_discrim
*discrim
))
4639 if (oper_has_access(source
, nickserv
, match
->opserv_level
, 0))
4640 nickserv_unregister_handle(match
, source
, nickserv
); // XXX nickserv hard coded
4645 search_add2ldap_func (struct userNode
*source
, struct handle_info
*match
, UNUSED_ARG(struct nickserv_discrim
*discrim
))
4648 if(match
->email_addr
&& match
->passwd
&& match
->handle
) {
4649 rc
= ldap_do_add(match
->handle
, match
->passwd
, match
->email_addr
);
4650 if(rc
!= LDAP_SUCCESS
) {
4651 send_message(source
, nickserv
, "NSMSG_LDAP_FAIL_ADD", match
->handle
, ldap_err2string(rc
));
4658 search_set_func (struct userNode
*source
, struct handle_info
*match
, struct nickserv_discrim
*discrim
)
4663 if (!(opt
= dict_find(nickserv_opt_dict
, discrim
->setwhat
, NULL
))) {
4667 oargv
[0] = (char *)discrim
->setwhat
;
4668 oargv
[1] = (char *)discrim
->setval
;
4670 opt(discrim
->cmd
, source
, match
, 1, 1, 2, oargv
);
4674 nickserv_sort_accounts_by_access(const void *a
, const void *b
)
4676 const struct handle_info
*hi_a
= *(const struct handle_info
**)a
;
4677 const struct handle_info
*hi_b
= *(const struct handle_info
**)b
;
4678 if (hi_a
->opserv_level
!= hi_b
->opserv_level
)
4679 return hi_b
->opserv_level
- hi_a
->opserv_level
;
4680 return irccasecmp(hi_a
->handle
, hi_b
->handle
);
4684 nickserv_show_oper_accounts(struct userNode
*user
, struct svccmd
*cmd
)
4686 struct handle_info_list hil
;
4687 struct helpfile_table tbl
;
4692 memset(&hil
, 0, sizeof(hil
));
4693 for (it
= dict_first(nickserv_handle_dict
); it
; it
= iter_next(it
)) {
4694 struct handle_info
*hi
= iter_data(it
);
4695 if (hi
->opserv_level
)
4696 handle_info_list_append(&hil
, hi
);
4698 qsort(hil
.list
, hil
.used
, sizeof(hil
.list
[0]), nickserv_sort_accounts_by_access
);
4699 tbl
.length
= hil
.used
+ 1;
4701 tbl
.flags
= TABLE_NO_FREE
| TABLE_REPEAT_ROWS
| TABLE_REPEAT_HEADERS
;
4702 tbl
.contents
= malloc(tbl
.length
* sizeof(tbl
.contents
[0]));
4703 tbl
.contents
[0] = ary
= malloc(tbl
.width
* sizeof(ary
[0]));
4706 for (ii
= 0; ii
< hil
.used
; ) {
4707 ary
= malloc(tbl
.width
* sizeof(ary
[0]));
4708 ary
[0] = hil
.list
[ii
]->handle
;
4709 ary
[1] = strtab(hil
.list
[ii
]->opserv_level
);
4710 tbl
.contents
[++ii
] = ary
;
4712 table_send(cmd
->parent
->bot
, user
->nick
, 0, NULL
, tbl
);
4713 /*reply("MSG_MATCH_COUNT", hil.used); */
4714 for (ii
= 0; ii
< hil
.used
; ii
++)
4715 free(tbl
.contents
[ii
]);
4720 static NICKSERV_FUNC(cmd_search
)
4722 struct nickserv_discrim
*discrim
;
4723 discrim_search_func action
;
4724 struct svccmd
*subcmd
;
4725 unsigned int matches
;
4728 NICKSERV_MIN_PARMS(3);
4729 sprintf(buf
, "search %s", argv
[1]);
4730 subcmd
= dict_find(nickserv_service
->commands
, buf
, NULL
);
4731 if (!irccasecmp(argv
[1], "print"))
4732 action
= search_print_func
;
4733 else if (!irccasecmp(argv
[1], "count"))
4734 action
= search_count_func
;
4735 else if (!irccasecmp(argv
[1], "unregister"))
4736 action
= search_unregister_func
;
4737 else if (!irccasecmp(argv
[1], "set"))
4738 action
= search_set_func
;
4740 else if (nickserv_conf
.ldap_enable
&& !irccasecmp(argv
[1], "add2ldap"))
4741 action
= search_add2ldap_func
;
4744 reply("NSMSG_INVALID_ACTION", argv
[1]);
4748 if (subcmd
&& !svccmd_can_invoke(user
, nickserv
, subcmd
, NULL
, SVCCMD_NOISY
))
4751 discrim
= nickserv_discrim_create(cmd
, user
, argc
-2, argv
+2);
4755 if (action
== search_print_func
)
4756 reply("NSMSG_ACCOUNT_SEARCH_RESULTS");
4757 else if (action
== search_count_func
)
4758 discrim
->limit
= INT_MAX
;
4759 else if ((action
== search_set_func
) && (!(discrim
->setwhat
) || !(discrim
->setval
)))
4760 return reply("MSG_MISSING_PARAMS", argv
[1]);
4762 matches
= nickserv_discrim_search(discrim
, action
, user
);
4765 reply("MSG_MATCH_COUNT", matches
);
4767 reply("MSG_NO_MATCHES");
4773 static MODCMD_FUNC(cmd_checkpass
)
4775 struct handle_info
*hi
;
4777 NICKSERV_MIN_PARMS(3);
4778 if (!(hi
= get_handle_info(argv
[1]))) {
4779 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
4782 if (checkpass(argv
[2], hi
->passwd
))
4783 reply("CHECKPASS_YES");
4785 reply("CHECKPASS_NO");
4790 static MODCMD_FUNC(cmd_checkemail
)
4792 struct handle_info
*hi
;
4794 NICKSERV_MIN_PARMS(3);
4795 if (!(hi
= modcmd_get_handle_info(user
, argv
[1]))) {
4798 if (!hi
->email_addr
)
4799 reply("CHECKEMAIL_NOT_SET");
4800 else if (!irccasecmp(argv
[2], hi
->email_addr
))
4801 reply("CHECKEMAIL_YES");
4803 reply("CHECKEMAIL_NO");
4808 nickserv_db_read_handle(char *handle
, dict_t obj
)
4811 struct string_list
*masks
, *sslfps
, *slist
, *ignores
;
4812 struct handle_info
*hi
;
4813 struct userNode
*authed_users
;
4814 struct userData
*channel_list
;
4817 unsigned long int id
;
4820 char *setter
, *note
;
4823 str
= database_get_data(obj
, KEY_ID
, RECDB_QSTRING
);
4824 id
= str
? strtoul(str
, NULL
, 0) : 0;
4825 str
= database_get_data(obj
, KEY_PASSWD
, RECDB_QSTRING
);
4827 log_module(NS_LOG
, LOG_WARNING
, "did not find a password for %s -- skipping user.", handle
);
4830 if ((hi
= get_handle_info(handle
))) {
4831 authed_users
= hi
->users
;
4832 channel_list
= hi
->channels
;
4834 hi
->channels
= NULL
;
4835 dict_remove(nickserv_handle_dict
, hi
->handle
);
4837 authed_users
= NULL
;
4838 channel_list
= NULL
;
4840 if(nickserv_conf
.force_handles_lowercase
)
4841 irc_strtolower(handle
);
4842 hi
= register_handle(handle
, str
, id
);
4844 hi
->users
= authed_users
;
4845 while (authed_users
) {
4846 authed_users
->handle_info
= hi
;
4847 authed_users
= authed_users
->next_authed
;
4850 hi
->channels
= channel_list
;
4851 masks
= database_get_data(obj
, KEY_MASKS
, RECDB_STRING_LIST
);
4852 hi
->masks
= masks
? string_list_copy(masks
) : alloc_string_list(1);
4853 sslfps
= database_get_data(obj
, KEY_SSLFPS
, RECDB_STRING_LIST
);
4854 hi
->sslfps
= sslfps
? string_list_copy(sslfps
) : alloc_string_list(1);
4855 ignores
= database_get_data(obj
, KEY_IGNORES
, RECDB_STRING_LIST
);
4856 hi
->ignores
= ignores
? string_list_copy(ignores
) : alloc_string_list(1);
4857 str
= database_get_data(obj
, KEY_MAXLOGINS
, RECDB_QSTRING
);
4858 hi
->maxlogins
= str
? strtoul(str
, NULL
, 0) : 0;
4859 str
= database_get_data(obj
, KEY_LANGUAGE
, RECDB_QSTRING
);
4860 hi
->language
= language_find(str
? str
: "C");
4861 str
= database_get_data(obj
, KEY_OPSERV_LEVEL
, RECDB_QSTRING
);
4862 hi
->opserv_level
= str
? strtoul(str
, NULL
, 0) : 0;
4863 str
= database_get_data(obj
, KEY_INFO
, RECDB_QSTRING
);
4865 hi
->infoline
= strdup(str
);
4866 str
= database_get_data(obj
, KEY_REGISTER_ON
, RECDB_QSTRING
);
4867 hi
->registered
= str
? (time_t)strtoul(str
, NULL
, 0) : now
;
4868 str
= database_get_data(obj
, KEY_LAST_SEEN
, RECDB_QSTRING
);
4869 hi
->lastseen
= str
? (time_t)strtoul(str
, NULL
, 0) : hi
->registered
;
4870 str
= database_get_data(obj
, KEY_KARMA
, RECDB_QSTRING
);
4871 hi
->karma
= str
? strtoul(str
, NULL
, 0) : 0;
4872 /* We want to read the nicks even if disable_nicks is set. This is so
4873 * that we don't lose the nick data entirely. */
4874 obj2
= database_get_data(obj
, KEY_NICKS_EX
, RECDB_OBJECT
);
4875 for(it
= dict_first(obj2
); it
; it
= iter_next(it
))
4877 struct record_data
*rd
= iter_data(it
);
4878 struct nick_info
* ni
;
4880 register_nick(iter_key(it
), hi
);
4881 ni
= get_nick_info(iter_key(it
));
4886 str
= database_get_data(rd
->d
.object
, KEY_REGISTER_ON
, RECDB_QSTRING
);
4887 ni
->registered
= str
? (time_t)strtoul(str
, NULL
, 0) : now
;
4888 str
= database_get_data(rd
->d
.object
, KEY_LAST_SEEN
, RECDB_QSTRING
);
4889 ni
->lastseen
= str
? (time_t)strtoul(str
, NULL
, 0) : ni
->registered
;
4892 slist
= database_get_data(obj
, KEY_NICKS
, RECDB_STRING_LIST
);
4894 for (ii
=0; ii
<slist
->used
; ii
++) {
4895 struct nick_info
* ni
;
4897 register_nick(slist
->list
[ii
], hi
);
4898 ni
= get_nick_info(slist
->list
[ii
]);
4903 ni
->registered
= hi
->registered
;
4904 ni
->lastseen
= ni
->registered
;
4908 str
= database_get_data(obj
, KEY_FLAGS
, RECDB_QSTRING
);
4910 for (ii
=0; str
[ii
]; ii
++)
4911 hi
->flags
|= 1 << (handle_inverse_flags
[(unsigned char)str
[ii
]] - 1);
4913 str
= database_get_data(obj
, KEY_USERLIST_STYLE
, RECDB_QSTRING
);
4914 hi
->userlist_style
= str
? str
[0] : HI_DEFAULT_STYLE
;
4915 str
= database_get_data(obj
, KEY_ANNOUNCEMENTS
, RECDB_QSTRING
);
4916 hi
->announcements
= str
? str
[0] : '?';
4917 str
= database_get_data(obj
, KEY_SCREEN_WIDTH
, RECDB_QSTRING
);
4918 hi
->screen_width
= str
? strtoul(str
, NULL
, 0) : 0;
4919 str
= database_get_data(obj
, KEY_TABLE_WIDTH
, RECDB_QSTRING
);
4920 hi
->table_width
= str
? strtoul(str
, NULL
, 0) : 0;
4921 str
= database_get_data(obj
, KEY_LAST_QUIT_HOST
, RECDB_QSTRING
);
4923 str
= database_get_data(obj
, KEY_LAST_AUTHED_HOST
, RECDB_QSTRING
);
4925 safestrncpy(hi
->last_quit_host
, str
, sizeof(hi
->last_quit_host
));
4926 str
= database_get_data(obj
, KEY_EMAIL_ADDR
, RECDB_QSTRING
);
4928 nickserv_set_email_addr(hi
, str
);
4929 str
= database_get_data(obj
, KEY_EPITHET
, RECDB_QSTRING
);
4931 hi
->epithet
= strdup(str
);
4932 subdb
= database_get_data(obj
, KEY_NOTE_NOTE
, RECDB_OBJECT
);
4934 setter
= database_get_data(subdb
, KEY_NOTE_SETTER
, RECDB_QSTRING
);
4935 str
= database_get_data(subdb
, KEY_NOTE_DATE
, RECDB_QSTRING
);
4936 date
= str
? (time_t)strtoul(str
, NULL
, 0) : now
;
4937 note
= database_get_data(subdb
, KEY_NOTE_NOTE
, RECDB_QSTRING
);
4938 if (setter
&& date
&& note
)
4940 if (!(hi
->note
= nickserv_add_note(setter
, date
, note
)))
4945 str
= database_get_data(obj
, KEY_FAKEHOST
, RECDB_QSTRING
);
4947 hi
->fakehost
= strdup(str
);
4949 subdb
= database_get_data(obj
, KEY_COOKIE
, RECDB_OBJECT
);
4951 const char *data
, *type
, *expires
, *cookie_str
;
4952 struct handle_cookie
*cookie
;
4954 cookie
= calloc(1, sizeof(*cookie
));
4955 type
= database_get_data(subdb
, KEY_COOKIE_TYPE
, RECDB_QSTRING
);
4956 data
= database_get_data(subdb
, KEY_COOKIE_DATA
, RECDB_QSTRING
);
4957 expires
= database_get_data(subdb
, KEY_COOKIE_EXPIRES
, RECDB_QSTRING
);
4958 cookie_str
= database_get_data(subdb
, KEY_COOKIE
, RECDB_QSTRING
);
4959 if (!type
|| !expires
|| !cookie_str
) {
4960 log_module(NS_LOG
, LOG_ERROR
, "Missing field(s) from cookie for account %s; dropping cookie.", hi
->handle
);
4963 if (!irccasecmp(type
, KEY_ACTIVATION
))
4964 cookie
->type
= ACTIVATION
;
4965 else if (!irccasecmp(type
, KEY_PASSWORD_CHANGE
))
4966 cookie
->type
= PASSWORD_CHANGE
;
4967 else if (!irccasecmp(type
, KEY_EMAIL_CHANGE
))
4968 cookie
->type
= EMAIL_CHANGE
;
4969 else if (!irccasecmp(type
, KEY_ALLOWAUTH
))
4970 cookie
->type
= ALLOWAUTH
;
4972 log_module(NS_LOG
, LOG_ERROR
, "Invalid cookie type %s for account %s; dropping cookie.", type
, handle
);
4975 cookie
->expires
= strtoul(expires
, NULL
, 0);
4976 if (cookie
->expires
< now
)
4979 cookie
->data
= strdup(data
);
4980 safestrncpy(cookie
->cookie
, cookie_str
, sizeof(cookie
->cookie
));
4984 nickserv_bake_cookie(cookie
);
4986 nickserv_free_cookie(cookie
);
4991 nickserv_saxdb_read(dict_t db
) {
4993 struct record_data
*rd
;
4996 for (it
=dict_first(db
); it
; it
=iter_next(it
)) {
4998 handle
= strdup(iter_key(it
));
4999 nickserv_db_read_handle(handle
, rd
->d
.object
);
5005 static NICKSERV_FUNC(cmd_mergedb
)
5007 struct timeval start
, stop
;
5010 NICKSERV_MIN_PARMS(2);
5011 gettimeofday(&start
, NULL
);
5012 if (!(db
= parse_database(argv
[1]))) {
5013 reply("NSMSG_DB_UNREADABLE", argv
[1]);
5016 nickserv_saxdb_read(db
);
5018 gettimeofday(&stop
, NULL
);
5019 stop
.tv_sec
-= start
.tv_sec
;
5020 stop
.tv_usec
-= start
.tv_usec
;
5021 if (stop
.tv_usec
< 0) {
5023 stop
.tv_usec
+= 1000000;
5025 reply("NSMSG_DB_MERGED", argv
[1], stop
.tv_sec
, stop
.tv_usec
/1000);
5030 expire_handles(UNUSED_ARG(void *data
))
5032 dict_iterator_t it
, next
;
5034 struct handle_info
*hi
;
5036 for (it
=dict_first(nickserv_handle_dict
); it
; it
=next
) {
5037 next
= iter_next(it
);
5039 if ((hi
->opserv_level
> 0)
5041 || HANDLE_FLAGGED(hi
, FROZEN
)
5042 || HANDLE_FLAGGED(hi
, NODELETE
)) {
5045 expiry
= hi
->channels
? nickserv_conf
.handle_expire_delay
: nickserv_conf
.nochan_handle_expire_delay
;
5046 if ((now
- hi
->lastseen
) > expiry
) {
5047 log_module(NS_LOG
, LOG_INFO
, "Expiring account %s for inactivity.", hi
->handle
);
5048 nickserv_unregister_handle(hi
, NULL
, NULL
);
5052 if (nickserv_conf
.handle_expire_frequency
)
5053 timeq_add(now
+ nickserv_conf
.handle_expire_frequency
, expire_handles
, NULL
);
5057 expire_nicks(UNUSED_ARG(void *data
))
5059 dict_iterator_t it
, next
;
5060 time_t expiry
= nickserv_conf
.nick_expire_delay
;
5061 struct nick_info
*ni
;
5062 struct userNode
*ui
;
5064 if (!(nickserv_conf
.expire_nicks
))
5067 for (it
=dict_first(nickserv_nick_dict
); it
; it
=next
) {
5068 next
= iter_next(it
);
5070 if ((ni
->owner
->opserv_level
> 0)
5071 || ((ui
= GetUserH(ni
->nick
)) && (ui
->handle_info
) && (ui
->handle_info
== ni
->owner
))
5072 || HANDLE_FLAGGED(ni
->owner
, FROZEN
)
5073 || HANDLE_FLAGGED(ni
->owner
, NODELETE
)) {
5076 if ((now
- ni
->lastseen
) > expiry
) {
5077 log_module(NS_LOG
, LOG_INFO
, "Expiring nick %s for inactivity.", ni
->nick
);
5082 if (nickserv_conf
.nick_expire_frequency
&& nickserv_conf
.expire_nicks
)
5083 timeq_add(now
+ nickserv_conf
.nick_expire_frequency
, expire_nicks
, NULL
);
5087 nickserv_load_dict(const char *fname
)
5091 if (!(file
= fopen(fname
, "r"))) {
5092 log_module(NS_LOG
, LOG_ERROR
, "Unable to open dictionary file %s: %s", fname
, strerror(errno
));
5095 while (fgets(line
, sizeof(line
), file
)) {
5098 if (line
[strlen(line
)-1] == '\n')
5099 line
[strlen(line
)-1] = 0;
5100 dict_insert(nickserv_conf
.weak_password_dict
, strdup(line
), NULL
);
5103 log_module(NS_LOG
, LOG_INFO
, "Loaded %d words into weak password dictionary.", dict_size(nickserv_conf
.weak_password_dict
));
5106 static enum reclaim_action
5107 reclaim_action_from_string(const char *str
) {
5109 return RECLAIM_NONE
;
5110 else if (!irccasecmp(str
, "warn"))
5111 return RECLAIM_WARN
;
5112 else if (!irccasecmp(str
, "svsnick"))
5113 return RECLAIM_SVSNICK
;
5114 else if (!irccasecmp(str
, "kill"))
5115 return RECLAIM_KILL
;
5117 return RECLAIM_NONE
;
5121 nickserv_conf_read(void)
5123 dict_t conf_node
, child
;
5126 struct string_list
*strlist
;
5128 if (!(conf_node
= conf_get_data(NICKSERV_CONF_NAME
, RECDB_OBJECT
))) {
5129 log_module(NS_LOG
, LOG_ERROR
, "config node `%s' is missing or has wrong type.", NICKSERV_CONF_NAME
);
5132 str
= database_get_data(conf_node
, KEY_VALID_HANDLE_REGEX
, RECDB_QSTRING
);
5134 str
= database_get_data(conf_node
, KEY_VALID_ACCOUNT_REGEX
, RECDB_QSTRING
);
5135 if (nickserv_conf
.valid_handle_regex_set
)
5136 regfree(&nickserv_conf
.valid_handle_regex
);
5138 int err
= regcomp(&nickserv_conf
.valid_handle_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
5139 nickserv_conf
.valid_handle_regex_set
= !err
;
5140 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_account_regex (error %d)", err
);
5142 nickserv_conf
.valid_handle_regex_set
= 0;
5144 str
= database_get_data(conf_node
, KEY_VALID_NICK_REGEX
, RECDB_QSTRING
);
5145 if (nickserv_conf
.valid_nick_regex_set
)
5146 regfree(&nickserv_conf
.valid_nick_regex
);
5148 int err
= regcomp(&nickserv_conf
.valid_nick_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
5149 nickserv_conf
.valid_nick_regex_set
= !err
;
5150 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_nick_regex (error %d)", err
);
5152 nickserv_conf
.valid_nick_regex_set
= 0;
5154 str
= database_get_data(conf_node
, KEY_VALID_FAKEHOST_REGEX
, RECDB_QSTRING
);
5155 if (nickserv_conf
.valid_fakehost_regex_set
)
5156 regfree(&nickserv_conf
.valid_fakehost_regex
);
5158 int err
= regcomp(&nickserv_conf
.valid_fakehost_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
5159 nickserv_conf
.valid_fakehost_regex_set
= !err
;
5160 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_fakehost_regex (error %d)", err
);
5162 nickserv_conf
.valid_fakehost_regex_set
= 0;
5164 str
= database_get_data(conf_node
, KEY_NICKS_PER_HANDLE
, RECDB_QSTRING
);
5166 str
= database_get_data(conf_node
, KEY_NICKS_PER_ACCOUNT
, RECDB_QSTRING
);
5167 nickserv_conf
.nicks_per_handle
= str
? strtoul(str
, NULL
, 0) : 4;
5168 str
= database_get_data(conf_node
, KEY_DISABLE_NICKS
, RECDB_QSTRING
);
5169 nickserv_conf
.disable_nicks
= str
? strtoul(str
, NULL
, 0) : 0;
5170 str
= database_get_data(conf_node
, KEY_DEFAULT_HOSTMASK
, RECDB_QSTRING
);
5171 nickserv_conf
.default_hostmask
= str
? !disabled_string(str
) : 0;
5172 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_LENGTH
, RECDB_QSTRING
);
5173 nickserv_conf
.password_min_length
= str
? strtoul(str
, NULL
, 0) : 0;
5174 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_DIGITS
, RECDB_QSTRING
);
5175 nickserv_conf
.password_min_digits
= str
? strtoul(str
, NULL
, 0) : 0;
5176 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_UPPER
, RECDB_QSTRING
);
5177 nickserv_conf
.password_min_upper
= str
? strtoul(str
, NULL
, 0) : 0;
5178 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_LOWER
, RECDB_QSTRING
);
5179 nickserv_conf
.password_min_lower
= str
? strtoul(str
, NULL
, 0) : 0;
5180 str
= database_get_data(conf_node
, KEY_DB_BACKUP_FREQ
, RECDB_QSTRING
);
5181 nickserv_conf
.db_backup_frequency
= str
? ParseInterval(str
) : 7200;
5182 str
= database_get_data(conf_node
, KEY_MODOPER_LEVEL
, RECDB_QSTRING
);
5183 nickserv_conf
.modoper_level
= str
? strtoul(str
, NULL
, 0) : 900;
5184 str
= database_get_data(conf_node
, KEY_SET_EPITHET_LEVEL
, RECDB_QSTRING
);
5185 nickserv_conf
.set_epithet_level
= str
? strtoul(str
, NULL
, 0) : 1;
5186 str
= database_get_data(conf_node
, KEY_SET_TITLE_LEVEL
, RECDB_QSTRING
);
5187 nickserv_conf
.set_title_level
= str
? strtoul(str
, NULL
, 0) : 900;
5188 str
= database_get_data(conf_node
, KEY_SET_FAKEHOST_LEVEL
, RECDB_QSTRING
);
5189 nickserv_conf
.set_fakehost_level
= str
? strtoul(str
, NULL
, 0) : 1000;
5190 str
= database_get_data(conf_node
, KEY_HANDLE_EXPIRE_FREQ
, RECDB_QSTRING
);
5192 str
= database_get_data(conf_node
, KEY_ACCOUNT_EXPIRE_FREQ
, RECDB_QSTRING
);
5193 nickserv_conf
.handle_expire_frequency
= str
? ParseInterval(str
) : 86400;
5194 str
= database_get_data(conf_node
, KEY_HANDLE_EXPIRE_DELAY
, RECDB_QSTRING
);
5196 str
= database_get_data(conf_node
, KEY_ACCOUNT_EXPIRE_DELAY
, RECDB_QSTRING
);
5197 nickserv_conf
.handle_expire_delay
= str
? ParseInterval(str
) : 86400*30;
5198 str
= database_get_data(conf_node
, KEY_NOCHAN_HANDLE_EXPIRE_DELAY
, RECDB_QSTRING
);
5200 str
= database_get_data(conf_node
, KEY_NOCHAN_ACCOUNT_EXPIRE_DELAY
, RECDB_QSTRING
);
5201 nickserv_conf
.nochan_handle_expire_delay
= str
? ParseInterval(str
) : 86400*15;
5202 str
= database_get_data(conf_node
, "warn_clone_auth", RECDB_QSTRING
);
5203 nickserv_conf
.warn_clone_auth
= str
? !disabled_string(str
) : 1;
5204 str
= database_get_data(conf_node
, "default_maxlogins", RECDB_QSTRING
);
5205 nickserv_conf
.default_maxlogins
= str
? strtoul(str
, NULL
, 0) : 2;
5206 str
= database_get_data(conf_node
, "hard_maxlogins", RECDB_QSTRING
);
5207 nickserv_conf
.hard_maxlogins
= str
? strtoul(str
, NULL
, 0) : 10;
5208 str
= database_get_data(conf_node
, KEY_OUNREGISTER_INACTIVE
, RECDB_QSTRING
);
5209 nickserv_conf
.ounregister_inactive
= str
? ParseInterval(str
) : 86400*28;
5210 str
= database_get_data(conf_node
, KEY_OUNREGISTER_FLAGS
, RECDB_QSTRING
);
5213 nickserv_conf
.ounregister_flags
= 0;
5215 unsigned int pos
= handle_inverse_flags
[(unsigned char)*str
];
5218 nickserv_conf
.ounregister_flags
|= 1 << (pos
- 1);
5220 if (!nickserv_conf
.disable_nicks
) {
5221 str
= database_get_data(conf_node
, "reclaim_action", RECDB_QSTRING
);
5222 nickserv_conf
.reclaim_action
= str
? reclaim_action_from_string(str
) : RECLAIM_NONE
;
5223 str
= database_get_data(conf_node
, "warn_nick_owned", RECDB_QSTRING
);
5224 nickserv_conf
.warn_nick_owned
= str
? enabled_string(str
) : 0;
5225 str
= database_get_data(conf_node
, "auto_reclaim_action", RECDB_QSTRING
);
5226 nickserv_conf
.auto_reclaim_action
= str
? reclaim_action_from_string(str
) : RECLAIM_NONE
;
5227 str
= database_get_data(conf_node
, "auto_reclaim_delay", RECDB_QSTRING
);
5228 nickserv_conf
.auto_reclaim_delay
= str
? ParseInterval(str
) : 0;
5229 str
= database_get_data(conf_node
, KEY_NICK_EXPIRE_FREQ
, RECDB_QSTRING
);
5230 nickserv_conf
.nick_expire_frequency
= str
? ParseInterval(str
) : 86400;
5231 str
= database_get_data(conf_node
, KEY_NICK_EXPIRE_DELAY
, RECDB_QSTRING
);
5232 nickserv_conf
.nick_expire_delay
= str
? ParseInterval(str
) : 86400*30;
5233 str
= database_get_data(conf_node
, "expire_nicks", RECDB_QSTRING
);
5234 nickserv_conf
.expire_nicks
= str
? enabled_string(str
) : 0;
5236 child
= database_get_data(conf_node
, KEY_FLAG_LEVELS
, RECDB_OBJECT
);
5237 for (it
=dict_first(child
); it
; it
=iter_next(it
)) {
5238 const char *key
= iter_key(it
), *value
;
5242 if (!strncasecmp(key
, "uc_", 3))
5243 flag
= toupper(key
[3]);
5244 else if (!strncasecmp(key
, "lc_", 3))
5245 flag
= tolower(key
[3]);
5249 if ((pos
= handle_inverse_flags
[flag
])) {
5250 value
= GET_RECORD_QSTRING((struct record_data
*)iter_data(it
));
5251 flag_access_levels
[pos
- 1] = strtoul(value
, NULL
, 0);
5254 if (nickserv_conf
.weak_password_dict
)
5255 dict_delete(nickserv_conf
.weak_password_dict
);
5256 nickserv_conf
.weak_password_dict
= dict_new();
5257 dict_set_free_keys(nickserv_conf
.weak_password_dict
, free
);
5258 dict_insert(nickserv_conf
.weak_password_dict
, strdup("password"), NULL
);
5259 dict_insert(nickserv_conf
.weak_password_dict
, strdup("<password>"), NULL
);
5260 str
= database_get_data(conf_node
, KEY_DICT_FILE
, RECDB_QSTRING
);
5262 nickserv_load_dict(str
);
5263 str
= database_get_data(conf_node
, KEY_NICK
, RECDB_QSTRING
);
5264 if (nickserv
&& str
)
5265 NickChange(nickserv
, str
, 0);
5266 str
= database_get_data(conf_node
, KEY_AUTOGAG_ENABLED
, RECDB_QSTRING
);
5267 nickserv_conf
.autogag_enabled
= str
? strtoul(str
, NULL
, 0) : 1;
5268 str
= database_get_data(conf_node
, KEY_AUTOGAG_DURATION
, RECDB_QSTRING
);
5269 nickserv_conf
.autogag_duration
= str
? ParseInterval(str
) : 1800;
5270 str
= database_get_data(conf_node
, KEY_EMAIL_VISIBLE_LEVEL
, RECDB_QSTRING
);
5271 nickserv_conf
.email_visible_level
= str
? strtoul(str
, NULL
, 0) : 800;
5272 str
= database_get_data(conf_node
, KEY_EMAIL_ENABLED
, RECDB_QSTRING
);
5273 nickserv_conf
.email_enabled
= str
? enabled_string(str
) : 0;
5274 str
= database_get_data(conf_node
, KEY_SYNC_LOG
, RECDB_QSTRING
);
5275 nickserv_conf
.sync_log
= str
? enabled_string(str
) : 0;
5276 str
= database_get_data(conf_node
, KEY_COOKIE_TIMEOUT
, RECDB_QSTRING
);
5277 nickserv_conf
.cookie_timeout
= str
? ParseInterval(str
) : 24*3600;
5278 str
= database_get_data(conf_node
, KEY_EMAIL_REQUIRED
, RECDB_QSTRING
);
5279 nickserv_conf
.email_required
= (nickserv_conf
.email_enabled
&& str
) ? enabled_string(str
) : 0;
5280 str
= database_get_data(conf_node
, KEY_ACCOUNTS_PER_EMAIL
, RECDB_QSTRING
);
5281 nickserv_conf
.handles_per_email
= str
? strtoul(str
, NULL
, 0) : 1;
5282 str
= database_get_data(conf_node
, KEY_EMAIL_SEARCH_LEVEL
, RECDB_QSTRING
);
5283 nickserv_conf
.email_search_level
= str
? strtoul(str
, NULL
, 0) : 600;
5284 str
= database_get_data(conf_node
, KEY_TITLEHOST_SUFFIX
, RECDB_QSTRING
);
5285 nickserv_conf
.titlehost_suffix
= str
? str
: "example.net";
5287 free_string_list(nickserv_conf
.denied_fakehost_words
);
5288 strlist
= database_get_data(conf_node
, KEY_DENIED_FAKEHOST_WORDS
, RECDB_STRING_LIST
);
5290 strlist
= string_list_copy(strlist
);
5292 strlist
= alloc_string_list(4);
5293 string_list_append(strlist
, strdup("sex"));
5294 string_list_append(strlist
, strdup("fuck"));
5296 nickserv_conf
.denied_fakehost_words
= strlist
;
5298 str
= database_get_data(conf_node
, KEY_DEFAULT_STYLE
, RECDB_QSTRING
);
5299 nickserv_conf
.default_style
= str
? str
[0] : HI_DEFAULT_STYLE
;
5301 str
= database_get_data(conf_node
, KEY_AUTO_OPER
, RECDB_QSTRING
);
5302 nickserv_conf
.auto_oper
= str
? str
: "";
5304 str
= database_get_data(conf_node
, KEY_AUTO_ADMIN
, RECDB_QSTRING
);
5305 nickserv_conf
.auto_admin
= str
? str
: "";
5307 str
= database_get_data(conf_node
, KEY_AUTO_OPER_PRIVS
, RECDB_QSTRING
);
5308 nickserv_conf
.auto_oper_privs
= str
? str
: "";
5310 str
= database_get_data(conf_node
, KEY_AUTO_ADMIN_PRIVS
, RECDB_QSTRING
);
5311 nickserv_conf
.auto_admin_privs
= str
? str
: "";
5313 str
= conf_get_data("server/network", RECDB_QSTRING
);
5314 nickserv_conf
.network_name
= str
? str
: "some IRC network";
5315 if (!nickserv_conf
.auth_policer_params
) {
5316 nickserv_conf
.auth_policer_params
= policer_params_new();
5317 policer_params_set(nickserv_conf
.auth_policer_params
, "size", "5");
5318 policer_params_set(nickserv_conf
.auth_policer_params
, "drain-rate", "0.05");
5320 child
= database_get_data(conf_node
, KEY_AUTH_POLICER
, RECDB_OBJECT
);
5321 for (it
=dict_first(child
); it
; it
=iter_next(it
))
5322 set_policer_param(iter_key(it
), iter_data(it
), nickserv_conf
.auth_policer_params
);
5324 str
= database_get_data(conf_node
, KEY_LDAP_ENABLE
, RECDB_QSTRING
);
5325 nickserv_conf
.ldap_enable
= str
? strtoul(str
, NULL
, 0) : 0;
5327 str
= database_get_data(conf_node
, KEY_FORCE_HANDLES_LOWERCASE
, RECDB_QSTRING
);
5328 nickserv_conf
.force_handles_lowercase
= str
? strtol(str
, NULL
, 0) : 0;
5331 if(nickserv_conf
.ldap_enable
> 0) {
5332 /* ldap is enabled but not compiled in - error out */
5333 log_module(MAIN_LOG
, LOG_ERROR
, "ldap is enabled in config, but not compiled in!");
5335 /* nickserv_conf.ldap_enable = 0; */
5341 str
= database_get_data(conf_node
, KEY_LDAP_URI
, RECDB_QSTRING
);
5342 nickserv_conf
.ldap_uri
= str
? str
: "";
5344 str
= database_get_data(conf_node
, KEY_LDAP_BASE
, RECDB_QSTRING
);
5345 nickserv_conf
.ldap_base
= str
? str
: "";
5347 str
= database_get_data(conf_node
, KEY_LDAP_DN_FMT
, RECDB_QSTRING
);
5348 nickserv_conf
.ldap_dn_fmt
= str
? str
: "";
5350 str
= database_get_data(conf_node
, KEY_LDAP_VERSION
, RECDB_QSTRING
);
5351 nickserv_conf
.ldap_version
= str
? strtoul(str
, NULL
, 0) : 3;
5353 str
= database_get_data(conf_node
, KEY_LDAP_AUTOCREATE
, RECDB_QSTRING
);
5354 nickserv_conf
.ldap_autocreate
= str
? strtoul(str
, NULL
, 0) : 0;
5356 str
= database_get_data(conf_node
, KEY_LDAP_TIMEOUT
, RECDB_QSTRING
);
5357 nickserv_conf
.ldap_timeout
= str
? strtoul(str
, NULL
, 0) : 5;
5359 str
= database_get_data(conf_node
, KEY_LDAP_ADMIN_DN
, RECDB_QSTRING
);
5360 nickserv_conf
.ldap_admin_dn
= str
? str
: "";
5362 str
= database_get_data(conf_node
, KEY_LDAP_ADMIN_PASS
, RECDB_QSTRING
);
5363 nickserv_conf
.ldap_admin_pass
= str
? str
: "";
5365 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_ACCOUNT
, RECDB_QSTRING
);
5366 nickserv_conf
.ldap_field_account
= str
? str
: "";
5368 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_PASSWORD
, RECDB_QSTRING
);
5369 nickserv_conf
.ldap_field_password
= str
? str
: "";
5371 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_EMAIL
, RECDB_QSTRING
);
5372 nickserv_conf
.ldap_field_email
= str
? str
: "";
5374 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_OSLEVEL
, RECDB_QSTRING
);
5375 nickserv_conf
.ldap_field_oslevel
= str
? str
: "";
5377 str
= database_get_data(conf_node
, KEY_LDAP_OPER_GROUP_DN
, RECDB_QSTRING
);
5378 nickserv_conf
.ldap_oper_group_dn
= str
? str
: "";
5380 str
= database_get_data(conf_node
, KEY_LDAP_OPER_GROUP_LEVEL
, RECDB_QSTRING
);
5381 nickserv_conf
.ldap_oper_group_level
= str
? strtoul(str
, NULL
, 0) : 99;
5383 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_GROUP_MEMBER
, RECDB_QSTRING
);
5384 nickserv_conf
.ldap_field_group_member
= str
? str
: "";
5386 free_string_list(nickserv_conf
.ldap_object_classes
);
5387 strlist
= database_get_data(conf_node
, KEY_LDAP_OBJECT_CLASSES
, RECDB_STRING_LIST
);
5389 strlist
= string_list_copy(strlist
);
5391 strlist
= alloc_string_list(4);
5392 string_list_append(strlist
, strdup("top"));
5394 nickserv_conf
.ldap_object_classes
= strlist
;
5401 nickserv_reclaim(struct userNode
*user
, struct nick_info
*ni
, enum reclaim_action action
) {
5403 char newnick
[NICKLEN
+1];
5416 send_message(user
, nickserv
, "NSMSG_RECLAIM_WARN", ni
->nick
, ni
->owner
->handle
);
5417 send_message(user
, nickserv
, "NSMSG_RECLAIM_HOWTO", ni
->owner
->handle
, nickserv
->nick
, self
->name
, ni
->owner
->handle
);
5419 case RECLAIM_SVSNICK
:
5421 snprintf(newnick
, sizeof(newnick
), "Guest%d", rand()%10000
);
5422 } while (GetUserH(newnick
));
5423 irc_svsnick(nickserv
, user
, newnick
);
5426 msg
= user_find_message(user
, "NSMSG_RECLAIM_KILL");
5427 DelUser(user
, nickserv
, 1, msg
);
5433 nickserv_reclaim_p(void *data
) {
5434 struct userNode
*user
= data
;
5435 struct nick_info
*ni
= get_nick_info(user
->nick
);
5437 nickserv_reclaim(user
, ni
, nickserv_conf
.auto_reclaim_action
);
5441 check_user_nick(struct userNode
*user
, UNUSED_ARG(void *extra
)) {
5442 struct nick_info
*ni
;
5443 user
->modes
&= ~FLAGS_REGNICK
;
5445 if (!(ni
= get_nick_info(user
->nick
)))
5447 if (user
->handle_info
== ni
->owner
) {
5448 user
->modes
|= FLAGS_REGNICK
;
5452 if (nickserv_conf
.warn_nick_owned
)
5453 send_message(user
, nickserv
, "NSMSG_RECLAIM_WARN", ni
->nick
, ni
->owner
->handle
);
5454 send_message(user
, nickserv
, "NSMSG_RECLAIM_HOWTO", ni
->owner
->handle
, nickserv
->nick
, self
->name
, ni
->owner
->handle
);
5455 if (nickserv_conf
.auto_reclaim_action
== RECLAIM_NONE
)
5457 if (nickserv_conf
.auto_reclaim_delay
)
5458 timeq_add(now
+ nickserv_conf
.auto_reclaim_delay
, nickserv_reclaim_p
, user
);
5460 nickserv_reclaim(user
, ni
, nickserv_conf
.auto_reclaim_action
);
5466 new_user_event(struct userNode
*user
, void *extra
) {
5467 /* If the user's server is not bursting,
5468 * the user is authed, the account has autohide set
5469 * and the user doesn't have user mode +x then apply
5470 * the autohide setting.
5472 if (!user
->uplink
->burst
&& user
->handle_info
&&
5473 HANDLE_FLAGGED(user
->handle_info
, AUTOHIDE
) &&
5474 !IsHiddenHost(user
))
5475 irc_umode(user
, "+x");
5477 return check_user_nick(user
, extra
);
5481 handle_account(struct userNode
*user
, const char *stamp
)
5483 struct handle_info
*hi
;
5486 #ifdef WITH_PROTOCOL_P10
5487 time_t timestamp
= 0;
5489 colon
= strchr(stamp
, ':');
5490 if(colon
&& colon
[1])
5493 timestamp
= atoi(colon
+1);
5495 hi
= dict_find(nickserv_handle_dict
, stamp
, NULL
);
5496 if(hi
&& timestamp
&& hi
->registered
!= timestamp
)
5498 log_module(MAIN_LOG
, LOG_WARNING
, "%s using account %s but timestamp does not match %s is not %s.", user
->nick
, stamp
, ctime(×tamp
),
5499 ctime(&hi
->registered
));
5503 hi
= dict_find(nickserv_id_dict
, stamp
, NULL
);
5504 log_module(MAIN_LOG
, LOG_WARNING
, "Using non-P10 code in accounts, not tested at all!");
5508 if(!hi
&& nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_autocreate
&&
5509 (ldap_user_exists(stamp
) == LDAP_SUCCESS
)) {
5515 /* First attempt to get the email address from LDAP */
5516 if((rc
= ldap_get_user_info(stamp
, &email
) != LDAP_SUCCESS
))
5517 if(nickserv_conf
.email_required
)
5520 /* Now try to register the handle */
5521 if (cont
&& (hi
= nickserv_register(user
, user
, stamp
, NULL
, 1))) {
5522 if(nickserv_conf
.default_hostmask
)
5525 mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
5528 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
5529 string_list_append(hi
->masks
, mask_canonicalized
);
5533 nickserv_set_email_addr(hi
, email
);
5541 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
5544 set_user_handle_info(user
, hi
, 0);
5546 log_module(MAIN_LOG
, LOG_WARNING
, "%s had unknown account stamp %s.", user
->nick
, stamp
);
5551 handle_nick_change(struct userNode
*user
, const char *old_nick
, UNUSED_ARG(void *extra
))
5553 struct handle_info
*hi
;
5555 if ((hi
= dict_find(nickserv_allow_auth_dict
, old_nick
, 0))) {
5556 dict_remove(nickserv_allow_auth_dict
, old_nick
);
5557 dict_insert(nickserv_allow_auth_dict
, user
->nick
, hi
);
5559 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
5560 check_user_nick(user
, NULL
);
5564 nickserv_remove_user(struct userNode
*user
, UNUSED_ARG(struct userNode
*killer
), UNUSED_ARG(const char *why
), UNUSED_ARG(void *extra
))
5566 dict_remove(nickserv_allow_auth_dict
, user
->nick
);
5567 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
5568 set_user_handle_info(user
, NULL
, 0);
5571 static struct modcmd
*
5572 nickserv_define_func(const char *name
, modcmd_func_t func
, int min_level
, int must_auth
, int must_be_qualified
)
5574 if (min_level
> 0) {
5576 sprintf(buf
, "%u", min_level
);
5577 if (must_be_qualified
) {
5578 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "level", buf
, "flags", "+qualified,+loghostmask", NULL
);
5580 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "level", buf
, NULL
);
5582 } else if (min_level
== 0) {
5583 if (must_be_qualified
) {
5584 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+helping", NULL
);
5586 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+helping", NULL
);
5589 if (must_be_qualified
) {
5590 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+qualified,+loghostmask", NULL
);
5592 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), NULL
);
5597 #define SDFLAG_STALE 0x01 /**< SASL session data is stale, delete on next pass. */
5601 struct SASLSession
*next
;
5602 struct SASLSession
*prev
;
5603 struct server
* source
;
5613 struct SASLSession
*saslsessions
= NULL
;
5616 sasl_delete_session(struct SASLSession
*session
)
5623 session
->buf
= NULL
;
5625 if (session
->sslclifp
)
5626 free(session
->sslclifp
);
5627 session
->sslclifp
= NULL
;
5629 if (session
->hostmask
)
5630 free(session
->hostmask
);
5631 session
->hostmask
= NULL
;
5634 session
->next
->prev
= session
->prev
;
5636 session
->prev
->next
= session
->next
;
5638 saslsessions
= session
->next
;
5644 sasl_delete_stale(UNUSED_ARG(void *data
))
5648 struct SASLSession
*sess
= NULL
;
5649 struct SASLSession
*nextsess
= NULL
;
5651 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Checking for stale sessions");
5653 for (sess
= saslsessions
; sess
; sess
= nextsess
)
5655 nextsess
= sess
->next
;
5657 if (sess
->flags
& SDFLAG_STALE
)
5660 sasl_delete_session(sess
);
5665 sess
->flags
|= SDFLAG_STALE
;
5670 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Deleted %d stale sessions, %d remaining", delcount
, remcount
);
5672 timeq_add(now
+ 30, sasl_delete_stale
, NULL
);
5676 sasl_get_session(const char *uid
)
5678 struct SASLSession
*sess
;
5680 for (sess
= saslsessions
; sess
; sess
= sess
->next
)
5682 if (!strncmp(sess
->uid
, uid
, 128))
5684 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Found session for %s", sess
->uid
);
5689 sess
= malloc(sizeof(struct SASLSession
));
5690 memset(sess
, 0, sizeof(struct SASLSession
));
5692 strncpy(sess
->uid
, uid
, 128);
5695 timeq_add(now
+ 30, sasl_delete_stale
, NULL
);
5698 saslsessions
->prev
= sess
;
5699 sess
->next
= saslsessions
;
5700 saslsessions
= sess
;
5702 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Created session for %s", sess
->uid
);
5707 sasl_packet(struct SASLSession
*session
)
5709 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Got packet containing: %s", session
->buf
);
5711 if (!session
->mech
[0])
5713 log_module(NS_LOG
, LOG_DEBUG
, "SASL: No mechanism stored yet, using %s", session
->buf
);
5714 if (strcmp(session
->buf
, "PLAIN") && (strcmp(session
->buf
, "EXTERNAL") || !session
->sslclifp
)) {
5715 if (!session
->sslclifp
)
5716 irc_sasl(session
->source
, session
->uid
, "M", "PLAIN");
5718 irc_sasl(session
->source
, session
->uid
, "M", "PLAIN,EXTERNAL");
5719 irc_sasl(session
->source
, session
->uid
, "D", "F");
5720 sasl_delete_session(session
);
5724 strncpy(session
->mech
, session
->buf
, 10);
5725 irc_sasl(session
->source
, session
->uid
, "C", "+");
5727 else if (!strcmp(session
->mech
, "EXTERNAL"))
5731 char *authzid
= NULL
;
5732 struct handle_info
*hi
= NULL
;
5733 static char buffer
[256];
5735 base64_decode_alloc(session
->buf
, session
->buflen
, &raw
, &rawlen
);
5740 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Checking supplied credentials");
5742 if (!session
->sslclifp
) {
5743 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Incomplete credentials supplied");
5744 irc_sasl(session
->source
, session
->uid
, "D", "F");
5746 if (!(hi
= loc_auth(session
->sslclifp
, authzid
, NULL
, session
->hostmask
)))
5748 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Invalid credentials supplied");
5749 irc_sasl(session
->source
, session
->uid
, "D", "F");
5753 snprintf(buffer
, sizeof(buffer
), "%s "FMT_TIME_T
, hi
->handle
, hi
->registered
);
5754 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Valid credentials supplied");
5755 irc_sasl(session
->source
, session
->uid
, "L", buffer
);
5756 irc_sasl(session
->source
, session
->uid
, "D", "S");
5760 sasl_delete_session(session
);
5769 char *authzid
= NULL
;
5770 char *authcid
= NULL
;
5771 char *passwd
= NULL
;
5773 unsigned int i
= 0, c
= 0;
5774 struct handle_info
*hi
= NULL
;
5775 struct handle_info
*hii
= NULL
;
5776 static char buffer
[256];
5778 base64_decode_alloc(session
->buf
, session
->buflen
, &raw
, &rawlen
);
5780 raw
= (char *)realloc(raw
, rawlen
+1);
5785 for (i
=0; i
<rawlen
; i
++)
5796 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Checking supplied credentials");
5798 if ((c
!= 2) || !(*authcid
))
5800 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Incomplete credentials supplied");
5801 irc_sasl(session
->source
, session
->uid
, "D", "F");
5805 if (!(hi
= loc_auth(session
->sslclifp
, authcid
, passwd
, session
->hostmask
)))
5807 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Invalid credentials supplied");
5808 irc_sasl(session
->source
, session
->uid
, "D", "F");
5812 if (*authzid
&& irccasecmp(authzid
, authcid
))
5814 if (HANDLE_FLAGGED(hi
, IMPERSONATE
))
5817 hi
= get_handle_info(authzid
);
5821 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Impersonation unauthorized");
5829 log_module(NS_LOG
, LOG_DEBUG
, "SASL: %s is ipersonating %s", hii
->handle
, hi
->handle
);
5830 snprintf(buffer
, sizeof(buffer
), "%s "FMT_TIME_T
, hii
->handle
, hii
->registered
);
5831 irc_sasl(session
->source
, session
->uid
, "I", buffer
);
5833 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Valid credentials supplied");
5834 snprintf(buffer
, sizeof(buffer
), "%s "FMT_TIME_T
, hi
->handle
, hi
->registered
);
5835 irc_sasl(session
->source
, session
->uid
, "L", buffer
);
5836 irc_sasl(session
->source
, session
->uid
, "D", "S");
5840 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Invalid credentials supplied");
5841 irc_sasl(session
->source
, session
->uid
, "D", "F");
5846 sasl_delete_session(session
);
5852 /* clear stale state */
5853 session
->flags
&= ~SDFLAG_STALE
;
5857 handle_sasl_input(struct server
* source
,const char *uid
, const char *subcmd
, const char *data
, const char *ext
, UNUSED_ARG(void *extra
))
5859 struct SASLSession
* sess
= sasl_get_session(uid
);
5860 int len
= strlen(data
);
5862 sess
->source
= source
;
5864 if (!strcmp(subcmd
, "D"))
5866 sasl_delete_session(sess
);
5870 if (!strcmp(subcmd
, "H")) {
5871 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Storing host mask %s", data
);
5872 sess
->hostmask
= strdup(data
);
5876 if (strcmp(subcmd
, "S") && strcmp(subcmd
, "C"))
5882 if (sess
->p
== NULL
)
5884 sess
->buf
= (char *)malloc(len
+ 1);
5885 sess
->p
= sess
->buf
;
5890 if (sess
->buflen
+ len
+ 1 > 8192) /* This is a little much... */
5892 irc_sasl(source
, uid
, "D", "F");
5893 sasl_delete_session(sess
);
5897 sess
->buf
= (char *)realloc(sess
->buf
, sess
->buflen
+ len
+ 1);
5898 sess
->p
= sess
->buf
+ sess
->buflen
;
5899 sess
->buflen
+= len
;
5902 memcpy(sess
->p
, data
, len
);
5903 sess
->buf
[len
] = '\0';
5906 sess
->sslclifp
= strdup(ext
);
5908 /* Messages not exactly 400 bytes are the end of a packet. */
5913 if (sess
->buf
!= NULL
)
5915 sess
->buf
= sess
->p
= NULL
;
5920 nickserv_db_cleanup(UNUSED_ARG(void* extra
))
5922 unreg_del_user_func(nickserv_remove_user
, NULL
);
5923 unreg_sasl_input_func(handle_sasl_input
, NULL
);
5924 userList_clean(&curr_helpers
);
5925 policer_params_delete(nickserv_conf
.auth_policer_params
);
5926 dict_delete(nickserv_handle_dict
);
5927 dict_delete(nickserv_nick_dict
);
5928 dict_delete(nickserv_opt_dict
);
5929 dict_delete(nickserv_allow_auth_dict
);
5930 dict_delete(nickserv_email_dict
);
5931 dict_delete(nickserv_id_dict
);
5932 dict_delete(nickserv_conf
.weak_password_dict
);
5933 free(auth_func_list
);
5934 free(auth_func_list_extra
);
5935 free(unreg_func_list
);
5936 free(unreg_func_list_extra
);
5938 free(rf_list_extra
);
5939 free(allowauth_func_list
);
5940 free(allowauth_func_list_extra
);
5941 free(handle_merge_func_list
);
5942 free(handle_merge_func_list_extra
);
5943 free(failpw_func_list
);
5944 free(failpw_func_list_extra
);
5945 if (nickserv_conf
.valid_handle_regex_set
)
5946 regfree(&nickserv_conf
.valid_handle_regex
);
5947 if (nickserv_conf
.valid_nick_regex_set
)
5948 regfree(&nickserv_conf
.valid_nick_regex
);
5951 void handle_loc_auth_oper(struct userNode
*user
, UNUSED_ARG(struct handle_info
*old_handle
), UNUSED_ARG(void *extra
)) {
5952 char *privv
[MAXNUMPARAMS
];
5955 if (!*nickserv_conf
.auto_oper
|| !user
->handle_info
)
5958 if (!IsOper(user
)) {
5959 if (*nickserv_conf
.auto_admin
&& user
->handle_info
->opserv_level
>= opserv_conf_admin_level()) {
5960 if (nickserv_conf
.auto_admin_privs
[0]) {
5961 irc_raw_privs(user
, nickserv_conf
.auto_admin_privs
);
5962 privc
= split_line(strdup(nickserv_conf
.auto_admin_privs
), false, MAXNUMPARAMS
, privv
);
5963 for (i
= 0; i
< privc
; i
++) {
5964 client_modify_priv_by_name(user
, privv
[i
], 1);
5967 irc_umode(user
, nickserv_conf
.auto_admin
);
5968 irc_sno(0x1, "%s (%s@%s) is now an IRC Administrator",
5969 user
->nick
, user
->ident
, user
->hostname
);
5970 send_message(user
, nickserv
, "NSMSG_AUTO_OPER_ADMIN");
5971 } else if (*nickserv_conf
.auto_oper
&& user
->handle_info
->opserv_level
) {
5972 if (nickserv_conf
.auto_oper_privs
[0]) {
5973 irc_raw_privs(user
, nickserv_conf
.auto_oper_privs
);
5974 privc
= split_line(strdup(nickserv_conf
.auto_oper_privs
), false, MAXNUMPARAMS
, privv
);
5975 for (i
= 0; i
< privc
; i
++) {
5976 client_modify_priv_by_name(user
, privv
[i
], 1);
5979 irc_umode(user
, nickserv_conf
.auto_oper
);
5980 irc_sno(0x1, "%s (%s@%s) is now an IRC Operator",
5981 user
->nick
, user
->ident
, user
->hostname
);
5982 send_message(user
, nickserv
, "NSMSG_AUTO_OPER");
5988 init_nickserv(const char *nick
)
5990 struct chanNode
*chan
;
5992 NS_LOG
= log_register_type("NickServ", "file:nickserv.log");
5993 reg_new_user_func(new_user_event
, NULL
);
5994 reg_nick_change_func(handle_nick_change
, NULL
);
5995 reg_del_user_func(nickserv_remove_user
, NULL
);
5996 reg_account_func(handle_account
);
5997 reg_auth_func(handle_loc_auth_oper
, NULL
);
5998 reg_sasl_input_func(handle_sasl_input
, NULL
);
6000 /* set up handle_inverse_flags */
6001 memset(handle_inverse_flags
, 0, sizeof(handle_inverse_flags
));
6002 for (i
=0; handle_flags
[i
]; i
++) {
6003 handle_inverse_flags
[(unsigned char)handle_flags
[i
]] = i
+ 1;
6004 flag_access_levels
[i
] = 0;
6005 /* ensure flag I requires a minimum of 999 if not set in the config */
6006 if ((unsigned char)handle_flags
[i
] == 'I')
6007 flag_access_levels
[i
] = 999;
6010 conf_register_reload(nickserv_conf_read
);
6011 nickserv_opt_dict
= dict_new();
6012 nickserv_email_dict
= dict_new();
6014 dict_set_free_keys(nickserv_email_dict
, free
);
6015 dict_set_free_data(nickserv_email_dict
, nickserv_free_email_addr
);
6017 nickserv_module
= module_register("NickServ", NS_LOG
, "nickserv.help", NULL
);
6018 /* Removed qualified_host as default requirement for AUTH, REGISTER, PASS, etc. nets
6019 * can enable it per command using modcmd. (its a shitty default IMO, and now in 1.3
6020 * a big pain to disable since its nolonger in the config file. ) -Rubin
6022 modcmd_register(nickserv_module
, "AUTH", cmd_auth
, 2, MODCMD_KEEP_BOUND
, "flags", "+loghostmask", NULL
);
6023 nickserv_define_func("ALLOWAUTH", cmd_allowauth
, 0, 1, 0);
6024 nickserv_define_func("REGISTER", cmd_register
, -1, 0, 0);
6025 nickserv_define_func("OREGISTER", cmd_oregister
, 0, 1, 0);
6026 nickserv_define_func("UNREGISTER", cmd_unregister
, -1, 1, 0);
6027 nickserv_define_func("OUNREGISTER", cmd_ounregister
, 0, 1, 0);
6028 nickserv_define_func("ADDMASK", cmd_addmask
, -1, 1, 0);
6029 nickserv_define_func("OADDMASK", cmd_oaddmask
, 0, 1, 0);
6030 nickserv_define_func("DELMASK", cmd_delmask
, -1, 1, 0);
6031 nickserv_define_func("ODELMASK", cmd_odelmask
, 0, 1, 0);
6032 nickserv_define_func("ADDSSLFP", cmd_addsslfp
, -1, 1, 0);
6033 nickserv_define_func("OADDSSLFP", cmd_oaddsslfp
, 0, 1, 0);
6034 nickserv_define_func("DELSSLFP", cmd_delsslfp
, -1, 1, 0);
6035 nickserv_define_func("ODELSSLFP", cmd_odelsslfp
, 0, 1, 0);
6036 nickserv_define_func("PASS", cmd_pass
, -1, 1, 0);
6037 nickserv_define_func("SET", cmd_set
, -1, 1, 0);
6038 nickserv_define_func("OSET", cmd_oset
, 0, 1, 0);
6039 nickserv_define_func("ACCOUNTINFO", cmd_handleinfo
, -1, 0, 0);
6040 nickserv_define_func("USERINFO", cmd_userinfo
, -1, 1, 0);
6041 nickserv_define_func("RENAME", cmd_rename_handle
, -1, 1, 0);
6042 nickserv_define_func("VACATION", cmd_vacation
, -1, 1, 0);
6043 nickserv_define_func("MERGE", cmd_merge
, 750, 1, 0);
6044 if (!nickserv_conf
.disable_nicks
) {
6045 /* nick management commands */
6046 nickserv_define_func("REGNICK", cmd_regnick
, -1, 1, 0);
6047 nickserv_define_func("OREGNICK", cmd_oregnick
, 0, 1, 0);
6048 nickserv_define_func("UNREGNICK", cmd_unregnick
, -1, 1, 0);
6049 nickserv_define_func("OUNREGNICK", cmd_ounregnick
, 0, 1, 0);
6050 nickserv_define_func("NICKINFO", cmd_nickinfo
, -1, 1, 0);
6051 nickserv_define_func("RECLAIM", cmd_reclaim
, -1, 1, 0);
6053 if (nickserv_conf
.email_enabled
) {
6054 nickserv_define_func("AUTHCOOKIE", cmd_authcookie
, -1, 0, 0);
6055 nickserv_define_func("RESETPASS", cmd_resetpass
, -1, 0, 0);
6056 nickserv_define_func("COOKIE", cmd_cookie
, -1, 0, 0);
6057 nickserv_define_func("DELCOOKIE", cmd_delcookie
, -1, 1, 0);
6058 nickserv_define_func("ODELCOOKIE", cmd_odelcookie
, 0, 1, 0);
6059 dict_insert(nickserv_opt_dict
, "EMAIL", opt_email
);
6061 nickserv_define_func("GHOST", cmd_ghost
, -1, 1, 0);
6062 /* ignore commands */
6063 nickserv_define_func("ADDIGNORE", cmd_addignore
, -1, 1, 0);
6064 nickserv_define_func("OADDIGNORE", cmd_oaddignore
, 0, 1, 0);
6065 nickserv_define_func("DELIGNORE", cmd_delignore
, -1, 1, 0);
6066 nickserv_define_func("ODELIGNORE", cmd_odelignore
, 0, 1, 0);
6067 /* miscellaneous commands */
6068 nickserv_define_func("STATUS", cmd_status
, -1, 0, 0);
6069 nickserv_define_func("SEARCH", cmd_search
, 100, 1, 0);
6070 nickserv_define_func("SEARCH UNREGISTER", NULL
, 800, 1, 0);
6071 nickserv_define_func("MERGEDB", cmd_mergedb
, 999, 1, 0);
6072 nickserv_define_func("CHECKPASS", cmd_checkpass
, 601, 1, 0);
6073 nickserv_define_func("CHECKEMAIL", cmd_checkemail
, 0, 1, 0);
6075 dict_insert(nickserv_opt_dict
, "INFO", opt_info
);
6076 dict_insert(nickserv_opt_dict
, "WIDTH", opt_width
);
6077 dict_insert(nickserv_opt_dict
, "TABLEWIDTH", opt_tablewidth
);
6078 dict_insert(nickserv_opt_dict
, "COLOR", opt_color
);
6079 dict_insert(nickserv_opt_dict
, "PRIVMSG", opt_privmsg
);
6080 dict_insert(nickserv_opt_dict
, "AUTOHIDE", opt_autohide
);
6081 dict_insert(nickserv_opt_dict
, "STYLE", opt_style
);
6082 dict_insert(nickserv_opt_dict
, "PASS", opt_password
);
6083 dict_insert(nickserv_opt_dict
, "PASSWORD", opt_password
);
6084 dict_insert(nickserv_opt_dict
, "FLAGS", opt_flags
);
6085 dict_insert(nickserv_opt_dict
, "ACCESS", opt_level
);
6086 dict_insert(nickserv_opt_dict
, "LEVEL", opt_level
);
6087 dict_insert(nickserv_opt_dict
, "EPITHET", opt_epithet
);
6088 dict_insert(nickserv_opt_dict
, "NOTE", opt_note
);
6089 if (nickserv_conf
.titlehost_suffix
) {
6090 dict_insert(nickserv_opt_dict
, "TITLE", opt_title
);
6091 dict_insert(nickserv_opt_dict
, "FAKEHOST", opt_fakehost
);
6093 dict_insert(nickserv_opt_dict
, "ANNOUNCEMENTS", opt_announcements
);
6094 dict_insert(nickserv_opt_dict
, "MAXLOGINS", opt_maxlogins
);
6095 dict_insert(nickserv_opt_dict
, "ADVANCED", opt_advanced
);
6096 dict_insert(nickserv_opt_dict
, "LANGUAGE", opt_language
);
6097 dict_insert(nickserv_opt_dict
, "KARMA", opt_karma
);
6099 nickserv_handle_dict
= dict_new();
6100 dict_set_free_keys(nickserv_handle_dict
, free
);
6101 dict_set_free_data(nickserv_handle_dict
, free_handle_info
);
6103 nickserv_id_dict
= dict_new();
6104 dict_set_free_keys(nickserv_id_dict
, free
);
6106 nickserv_nick_dict
= dict_new();
6107 dict_set_free_data(nickserv_nick_dict
, free
);
6109 nickserv_allow_auth_dict
= dict_new();
6111 userList_init(&curr_helpers
);
6114 const char *modes
= conf_get_data("services/nickserv/modes", RECDB_QSTRING
);
6115 nickserv
= AddLocalUser(nick
, nick
, NULL
, "Nick Services", modes
);
6116 nickserv_service
= service_register(nickserv
);
6118 saxdb_register("NickServ", nickserv_saxdb_read
, nickserv_saxdb_write
);
6119 reg_exit_func(nickserv_db_cleanup
, NULL
);
6120 if(nickserv_conf
.handle_expire_frequency
)
6121 timeq_add(now
+ nickserv_conf
.handle_expire_frequency
, expire_handles
, NULL
);
6122 if(nickserv_conf
.nick_expire_frequency
&& nickserv_conf
.expire_nicks
)
6123 timeq_add(now
+ nickserv_conf
.nick_expire_frequency
, expire_nicks
, NULL
);
6125 if(autojoin_channels
&& nickserv
) {
6126 for (i
= 0; i
< autojoin_channels
->used
; i
++) {
6127 chan
= AddChannel(autojoin_channels
->list
[i
], now
, "+nt", NULL
, NULL
);
6128 AddChannelUser(nickserv
, chan
)->modes
|= MODE_CHANOP
;
6133 ldap_do_init(nickserv_conf
);
6136 message_register_table(msgtab
);