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
;
2131 if (nickserv_conf
.ldap_enable
&& (password
!= NULL
)) {
2132 ldap_result
= ldap_check_auth(handle
, password
);
2133 if (!hi
&& (ldap_result
!= LDAP_SUCCESS
))
2135 if (ldap_result
== LDAP_SUCCESS
) {
2136 /* Mark auth as successful */
2140 if (!hi
&& (ldap_result
== LDAP_SUCCESS
) && nickserv_conf
.ldap_autocreate
) {
2141 /* user not found, but authed to ldap successfully..
2142 * create the account.
2147 /* Add a *@* mask */
2148 /* TODO if userhost is not null, build mask based on that. */
2149 if(nickserv_conf
.default_hostmask
)
2152 return NULL
; /* They dont have a *@* mask so they can't loc */
2154 if(!(hi
= nickserv_register(NULL
, NULL
, handle
, password
, 0))) {
2155 return 0; /* couldn't add the user for some reason */
2158 if((rc
= ldap_get_user_info(handle
, &email
) != LDAP_SUCCESS
))
2160 if(nickserv_conf
.email_required
) {
2165 nickserv_set_email_addr(hi
, email
);
2169 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
2170 string_list_append(hi
->masks
, mask_canonicalized
);
2172 if(nickserv_conf
.sync_log
)
2173 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, "@", handle
);
2178 /* hi should now be a valid handle, if not return NULL */
2183 if (password
&& *password
&& !nickserv_conf
.ldap_enable
) {
2185 if (password
&& *password
) {
2187 if (checkpass(password
, hi
->passwd
))
2191 if (!auth
&& sslfp
&& *sslfp
&& hi
->sslfps
->used
) {
2192 /* If any SSL fingerprint matches, allow it. */
2193 for (ii
=0; ii
<hi
->sslfps
->used
; ii
++) {
2194 if (!irccasecmp(sslfp
, hi
->sslfps
->list
[ii
])) {
2201 /* Auth should have succeeded by this point */
2205 /* We don't know the users hostname, or anything because they
2206 * havn't registered yet. So we can only allow LOC if your
2207 * account has *@* as a hostmask.
2209 * UPDATE: New nefarious LOC supports u@h
2214 char *realhost
= NULL
;
2221 buf
= strdup(userhost
);
2224 for (c
= buf
; *c
; c
++) {
2225 if ((realhost
== NULL
) && (*c
== '@')) {
2232 } else if (bracket
&& (ip
== NULL
) && (*c
== ']')) {
2235 } else if (!bracket
&& (ip
== NULL
) && (*c
== ':')) {
2242 log_module(NS_LOG
, LOG_DEBUG
, "LOC: ident=%s host=%s ip=%s", ident
, realhost
, ip
);
2244 if(!ip
|| !realhost
|| !ident
) {
2246 return NULL
; /* Invalid AC request, just quit */
2248 uh
= malloc(strlen(userhost
));
2249 ui
= malloc(strlen(userhost
));
2250 sprintf(uh
, "%s@%s", ident
, realhost
);
2251 sprintf(ui
, "%s@%s", ident
, ip
);
2252 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
2254 if(match_ircglob(uh
, hi
->masks
->list
[ii
])
2255 || match_ircglob(ui
, hi
->masks
->list
[ii
]))
2267 for (ii
=0; ii
<hi
->masks
->used
; ii
++)
2269 if (!strcmp(hi
->masks
->list
[ii
], "*@*"))
2279 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2283 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
2284 for (used
= 0, other
= hi
->users
; other
; other
= other
->next_authed
) {
2285 if (++used
>= maxlogins
) {
2289 /* TODO - Add LOGGING to this function so LOC's are logged.. */
2293 static NICKSERV_FUNC(cmd_auth
)
2295 int pw_arg
, used
, maxlogins
;
2297 struct handle_info
*hi
;
2300 struct userNode
*other
;
2302 int ldap_result
= LDAP_OTHER
;
2306 if (user
->handle_info
) {
2307 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2310 if (IsStamped(user
)) {
2311 /* Unauthenticated users might still have been stamped
2312 previously and could therefore have a hidden host;
2313 do not allow them to authenticate. */
2314 reply("NSMSG_STAMPED_AUTH");
2321 hi
= dict_find(nickserv_handle_dict
, argv
[1], NULL
);
2322 } else if (argc
== 2) {
2325 if (nickserv_conf
.disable_nicks
) {
2326 hi
= get_handle_info(user
->nick
);
2328 /* try to look up their handle from their nick */
2329 /* TODO: handle ldap auth on nickserv style networks, too */
2330 struct nick_info
*ni
;
2331 ni
= get_nick_info(user
->nick
);
2333 reply("NSMSG_NICK_NOT_REGISTERED", user
->nick
);
2339 handle
= hi
->handle
;
2341 handle
= user
->nick
;
2344 reply("MSG_MISSING_PARAMS", argv
[0]);
2345 svccmd_send_help_brief(user
, nickserv
, cmd
);
2350 if(strchr(handle
, '<') || strchr(handle
, '>')) {
2351 reply("NSMSG_NO_ANGLEBRACKETS");
2354 if (!is_valid_handle(handle
)) {
2355 reply("NSMSG_BAD_HANDLE", handle
);
2359 if(nickserv_conf
.ldap_enable
) {
2360 ldap_result
= ldap_check_auth(handle
, passwd
);
2361 /* Get the users email address and update it */
2362 if(ldap_result
== LDAP_SUCCESS
) {
2364 if((rc
= ldap_get_user_info(handle
, &email
) != LDAP_SUCCESS
))
2366 if(nickserv_conf
.email_required
) {
2367 reply("NSMSG_LDAP_FAIL_GET_EMAIL", ldap_err2string(rc
));
2372 else if(ldap_result
!= LDAP_INVALID_CREDENTIALS
) {
2373 reply("NSMSG_LDAP_FAIL", ldap_err2string(ldap_result
));
2381 if(nickserv_conf
.ldap_enable
&& ldap_result
== LDAP_SUCCESS
&& nickserv_conf
.ldap_autocreate
) {
2382 /* user not found, but authed to ldap successfully..
2383 * create the account.
2386 if(!(hi
= nickserv_register(user
, user
, handle
, passwd
, 0))) {
2387 reply("NSMSG_UNABLE_TO_ADD");
2388 return 0; /* couldn't add the user for some reason */
2390 /* Add a *@* mask */
2391 if(nickserv_conf
.default_hostmask
)
2394 mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2397 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
2398 string_list_append(hi
->masks
, mask_canonicalized
);
2401 nickserv_set_email_addr(hi
, email
);
2404 if(nickserv_conf
.sync_log
)
2405 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, email
? email
: "@", user
->info
);
2409 reply("NSMSG_HANDLE_NOT_FOUND");
2415 /* Responses from here on look up the language used by the handle they asked about. */
2416 if (!valid_user_for(user
, hi
)) {
2417 if (hi
->email_addr
&& nickserv_conf
.email_enabled
)
2418 send_message_type(4, user
, cmd
->parent
->bot
,
2419 handle_find_message(hi
, "NSMSG_USE_AUTHCOOKIE"),
2422 send_message_type(4, user
, cmd
->parent
->bot
,
2423 handle_find_message(hi
, "NSMSG_HOSTMASK_INVALID"),
2425 argv
[pw_arg
] = "BADMASK";
2429 if (valid_user_sslfp(user
, hi
))
2433 if(( ( nickserv_conf
.ldap_enable
&& ldap_result
== LDAP_INVALID_CREDENTIALS
) ||
2434 ( (!nickserv_conf
.ldap_enable
) && (!checkpass(passwd
, hi
->passwd
)) ) ) && !sslfpauth
) {
2436 if (!checkpass(passwd
, hi
->passwd
) && !sslfpauth
) {
2439 send_message_type(4, user
, cmd
->parent
->bot
,
2440 handle_find_message(hi
, "NSMSG_PASSWORD_INVALID"));
2441 argv
[pw_arg
] = "BADPASS";
2442 for (n
=0; n
<failpw_func_used
; n
++)
2443 failpw_func_list
[n
](user
, hi
, failpw_func_list_extra
[n
]);
2444 if (nickserv_conf
.autogag_enabled
) {
2445 if (!user
->auth_policer
.params
) {
2446 user
->auth_policer
.last_req
= now
;
2447 user
->auth_policer
.params
= nickserv_conf
.auth_policer_params
;
2449 if (!policer_conforms(&user
->auth_policer
, now
, 1.0)) {
2451 hostmask
= generate_hostmask(user
, GENMASK_STRICT_HOST
|GENMASK_BYIP
|GENMASK_NO_HIDING
);
2452 log_module(NS_LOG
, LOG_INFO
, "%s auto-gagged for repeated password guessing.", hostmask
);
2453 gag_create(hostmask
, nickserv
->nick
, "Repeated password guessing.", now
+nickserv_conf
.autogag_duration
);
2455 argv
[pw_arg
] = "GAGGED";
2460 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2461 send_message_type(4, user
, cmd
->parent
->bot
,
2462 handle_find_message(hi
, "NSMSG_HANDLE_SUSPENDED"));
2463 argv
[pw_arg
] = "SUSPENDED";
2466 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
2467 for (used
= 0, other
= hi
->users
; other
; other
= other
->next_authed
) {
2468 if (++used
>= maxlogins
) {
2469 send_message_type(4, user
, cmd
->parent
->bot
,
2470 handle_find_message(hi
, "NSMSG_MAX_LOGINS"),
2472 argv
[pw_arg
] = "MAXLOGINS";
2477 set_user_handle_info(user
, hi
, 1);
2478 if (nickserv_conf
.email_required
&& !hi
->email_addr
)
2479 reply("NSMSG_PLEASE_SET_EMAIL");
2480 if (!sslfpauth
&& !is_secure_password(hi
->handle
, passwd
, NULL
))
2481 reply("NSMSG_WEAK_PASSWORD");
2482 if (!sslfpauth
&& (hi
->passwd
[0] != '$'))
2483 cryptpass(passwd
, hi
->passwd
);
2485 /* If a channel was waiting for this user to auth,
2486 * finish adding them */
2487 process_adduser_pending(user
);
2489 reply("NSMSG_AUTH_SUCCESS");
2492 /* Set +x if autohide is on */
2493 if(HANDLE_FLAGGED(hi
, AUTOHIDE
))
2494 irc_umode(user
, "+x");
2496 if (!hi
->masks
->used
) {
2498 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
2499 if (irc_in_addr_is_valid(user
->ip
) && irc_pton(&ip
, NULL
, user
->hostname
))
2500 string_list_append(hi
->masks
, generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_BYIP
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
));
2503 /* Wipe out the pass for the logs */
2504 argv
[pw_arg
] = "****";
2508 static allowauth_func_t
*allowauth_func_list
;
2509 static void **allowauth_func_list_extra
;
2510 static unsigned int allowauth_func_size
= 0, allowauth_func_used
= 0;
2513 reg_allowauth_func(allowauth_func_t func
, void *extra
)
2515 if (allowauth_func_used
== allowauth_func_size
) {
2516 if (allowauth_func_size
) {
2517 allowauth_func_size
<<= 1;
2518 allowauth_func_list
= realloc(allowauth_func_list
, allowauth_func_size
*sizeof(allowauth_func_t
));
2519 allowauth_func_list_extra
= realloc(allowauth_func_list_extra
, allowauth_func_size
*sizeof(void*));
2521 allowauth_func_size
= 8;
2522 allowauth_func_list
= malloc(allowauth_func_size
*sizeof(allowauth_func_t
));
2523 allowauth_func_list_extra
= malloc(allowauth_func_size
*sizeof(void*));
2526 allowauth_func_list
[allowauth_func_used
] = func
;
2527 allowauth_func_list_extra
[allowauth_func_used
++] = extra
;
2530 static NICKSERV_FUNC(cmd_allowauth
)
2532 struct userNode
*target
;
2533 struct handle_info
*hi
;
2536 NICKSERV_MIN_PARMS(2);
2537 if (!(target
= GetUserH(argv
[1]))) {
2538 reply("MSG_NICK_UNKNOWN", argv
[1]);
2541 if (target
->handle_info
) {
2542 reply("NSMSG_USER_PREV_AUTH", target
->nick
);
2545 if (IsStamped(target
)) {
2546 /* Unauthenticated users might still have been stamped
2547 previously and could therefore have a hidden host;
2548 do not allow them to authenticate to an account. */
2549 reply("NSMSG_USER_PREV_STAMP", target
->nick
);
2554 else if (!(hi
= get_handle_info(argv
[2]))) {
2555 reply("MSG_HANDLE_UNKNOWN", argv
[2]);
2559 if (hi
->opserv_level
> user
->handle_info
->opserv_level
) {
2560 reply("MSG_USER_OUTRANKED", hi
->handle
);
2563 if (((hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
))
2564 || (hi
->opserv_level
> 0))
2565 && ((argc
< 4) || irccasecmp(argv
[3], "staff"))) {
2566 reply("NSMSG_ALLOWAUTH_STAFF", hi
->handle
);
2569 dict_insert(nickserv_allow_auth_dict
, target
->nick
, hi
);
2570 reply("NSMSG_AUTH_ALLOWED", target
->nick
, hi
->handle
);
2571 send_message(target
, nickserv
, "NSMSG_AUTH_ALLOWED_MSG", hi
->handle
, hi
->handle
);
2572 if (nickserv_conf
.email_enabled
)
2573 send_message(target
, nickserv
, "NSMSG_AUTH_ALLOWED_EMAIL");
2575 if (dict_remove(nickserv_allow_auth_dict
, target
->nick
))
2576 reply("NSMSG_AUTH_NORMAL_ONLY", target
->nick
);
2578 reply("NSMSG_AUTH_UNSPECIAL", target
->nick
);
2580 for (n
=0; n
<allowauth_func_used
; n
++)
2581 allowauth_func_list
[n
](user
, target
, hi
, allowauth_func_list_extra
[n
]);
2585 static NICKSERV_FUNC(cmd_authcookie
)
2587 struct handle_info
*hi
;
2589 NICKSERV_MIN_PARMS(2);
2590 if (user
->handle_info
) {
2591 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2594 if (IsStamped(user
)) {
2595 /* Unauthenticated users might still have been stamped
2596 previously and could therefore have a hidden host;
2597 do not allow them to authenticate to an account. */
2598 reply("NSMSG_STAMPED_AUTHCOOKIE");
2601 if (!(hi
= get_handle_info(argv
[1]))) {
2602 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2605 if (!hi
->email_addr
) {
2606 reply("MSG_SET_EMAIL_ADDR");
2609 nickserv_make_cookie(user
, hi
, ALLOWAUTH
, NULL
, 0);
2613 static NICKSERV_FUNC(cmd_delcookie
)
2615 struct handle_info
*hi
;
2617 hi
= user
->handle_info
;
2619 reply("NSMSG_NO_COOKIE");
2622 switch (hi
->cookie
->type
) {
2625 reply("NSMSG_MUST_TIME_OUT");
2628 nickserv_eat_cookie(hi
->cookie
);
2629 reply("NSMSG_ATE_COOKIE");
2635 static NICKSERV_FUNC(cmd_odelcookie
)
2637 struct handle_info
*hi
;
2639 NICKSERV_MIN_PARMS(2);
2641 if (!(hi
= get_victim_oper(user
, argv
[1])))
2645 reply("NSMSG_NO_COOKIE_FOREIGN", hi
->handle
);
2649 switch (hi
->cookie
->type
) {
2651 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2653 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2655 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2656 /* Falied to update password in ldap, but still
2657 * updated it here.. what should we do? */
2658 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2663 if (nickserv_conf
.sync_log
)
2664 SyncLog("ACCOUNTACC %s", hi
->handle
);
2666 case PASSWORD_CHANGE
:
2673 reply("NSMSG_BAD_COOKIE_TYPE", hi
->cookie
->type
);
2674 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d for account %s.", hi
->cookie
->type
, hi
->handle
);
2678 nickserv_eat_cookie(hi
->cookie
);
2679 reply("NSMSG_ATE_FOREIGN_COOKIE", hi
->handle
);
2684 static NICKSERV_FUNC(cmd_resetpass
)
2686 struct handle_info
*hi
;
2687 char crypted
[MD5_CRYPT_LENGTH
];
2690 NICKSERV_MIN_PARMS(3);
2691 if(argc
>= 4 && !strcmp(argv
[3], "WEBLINK"))
2695 if (user
->handle_info
) {
2696 reply("NSMSG_ALREADY_AUTHED", user
->handle_info
->handle
);
2699 if (IsStamped(user
)) {
2700 /* Unauthenticated users might still have been stamped
2701 previously and could therefore have a hidden host;
2702 do not allow them to activate an account. */
2703 reply("NSMSG_STAMPED_RESETPASS");
2706 if (!(hi
= get_handle_info(argv
[1]))) {
2707 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2710 if (!hi
->email_addr
) {
2711 reply("MSG_SET_EMAIL_ADDR");
2714 cryptpass(argv
[2], crypted
);
2716 nickserv_make_cookie(user
, hi
, PASSWORD_CHANGE
, crypted
, weblink
);
2720 static NICKSERV_FUNC(cmd_cookie
)
2722 struct handle_info
*hi
;
2725 if ((argc
== 2) && (hi
= user
->handle_info
) && hi
->cookie
&& (hi
->cookie
->type
== EMAIL_CHANGE
)) {
2728 NICKSERV_MIN_PARMS(3);
2729 if (!(hi
= get_handle_info(argv
[1]))) {
2730 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
2736 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
2737 reply("NSMSG_HANDLE_SUSPENDED");
2742 reply("NSMSG_NO_COOKIE");
2746 /* Check validity of operation before comparing cookie to
2747 * prohibit guessing by authed users. */
2748 if (user
->handle_info
2749 && (hi
->cookie
->type
!= EMAIL_CHANGE
)
2750 && (hi
->cookie
->type
!= PASSWORD_CHANGE
)) {
2751 reply("NSMSG_CANNOT_COOKIE");
2755 if (strcmp(cookie
, hi
->cookie
->cookie
)) {
2756 reply("NSMSG_BAD_COOKIE");
2760 switch (hi
->cookie
->type
) {
2763 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2765 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2766 /* Falied to update email in ldap, but still
2767 * updated it here.. what should we do? */
2768 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2773 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2774 set_user_handle_info(user
, hi
, 1);
2775 reply("NSMSG_HANDLE_ACTIVATED");
2776 if (nickserv_conf
.sync_log
)
2777 SyncLog("ACCOUNTACC %s", hi
->handle
);
2779 case PASSWORD_CHANGE
:
2781 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2783 if((rc
= ldap_do_modify(hi
->handle
, hi
->cookie
->data
, NULL
)) != LDAP_SUCCESS
) {
2784 /* Falied to update email in ldap, but still
2785 * updated it here.. what should we do? */
2786 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2791 set_user_handle_info(user
, hi
, 1);
2792 safestrncpy(hi
->passwd
, hi
->cookie
->data
, sizeof(hi
->passwd
));
2793 reply("NSMSG_PASSWORD_CHANGED");
2794 if (nickserv_conf
.sync_log
)
2795 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
2799 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2801 if((rc
= ldap_do_modify(hi
->handle
, NULL
, hi
->cookie
->data
)) != LDAP_SUCCESS
) {
2802 /* Falied to update email in ldap, but still
2803 * updated it here.. what should we do? */
2804 reply("NSMSG_LDAP_FAIL_SEND_EMAIL", ldap_err2string(rc
));
2809 if (!hi
->email_addr
&& nickserv_conf
.sync_log
) {
2811 * This should only happen if an OREGISTER was sent. Require
2812 * email must be enabled! - SiRVulcaN
2814 if (nickserv_conf
.sync_log
)
2815 SyncLog("REGISTER %s %s %s %s", hi
->handle
, hi
->passwd
, hi
->cookie
->data
, user
->info
);
2818 nickserv_set_email_addr(hi
, hi
->cookie
->data
);
2819 reply("NSMSG_EMAIL_CHANGED");
2820 if (nickserv_conf
.sync_log
)
2821 SyncLog("EMAILCHANGE %s %s", hi
->handle
, hi
->cookie
->data
);
2824 char *mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2825 set_user_handle_info(user
, hi
, 1);
2826 nickserv_addmask(user
, hi
, mask
);
2827 reply("NSMSG_AUTH_SUCCESS");
2832 reply("NSMSG_BAD_COOKIE_TYPE", hi
->cookie
->type
);
2833 log_module(NS_LOG
, LOG_ERROR
, "Bad cookie type %d for account %s.", hi
->cookie
->type
, hi
->handle
);
2837 nickserv_eat_cookie(hi
->cookie
);
2839 process_adduser_pending(user
);
2844 static NICKSERV_FUNC(cmd_oregnick
) {
2846 struct handle_info
*target
;
2847 struct nick_info
*ni
;
2849 NICKSERV_MIN_PARMS(3);
2850 if (!(target
= modcmd_get_handle_info(user
, argv
[1])))
2853 if (!is_registerable_nick(nick
)) {
2854 reply("NSMSG_BAD_NICK", nick
);
2857 ni
= dict_find(nickserv_nick_dict
, nick
, NULL
);
2859 reply("NSMSG_NICK_EXISTS", nick
);
2862 register_nick(nick
, target
);
2863 reply("NSMSG_OREGNICK_SUCCESS", nick
, target
->handle
);
2867 static NICKSERV_FUNC(cmd_regnick
) {
2869 struct nick_info
*ni
;
2871 if (!is_registerable_nick(user
->nick
)) {
2872 reply("NSMSG_BAD_NICK", user
->nick
);
2875 /* count their nicks, see if it's too many */
2876 for (n
=0,ni
=user
->handle_info
->nicks
; ni
; n
++,ni
=ni
->next
) ;
2877 if (n
>= nickserv_conf
.nicks_per_handle
) {
2878 reply("NSMSG_TOO_MANY_NICKS");
2881 ni
= dict_find(nickserv_nick_dict
, user
->nick
, NULL
);
2883 reply("NSMSG_NICK_EXISTS", user
->nick
);
2886 register_nick(user
->nick
, user
->handle_info
);
2887 reply("NSMSG_REGNICK_SUCCESS", user
->nick
);
2891 static NICKSERV_FUNC(cmd_pass
)
2893 struct handle_info
*hi
;
2894 char *old_pass
, *new_pass
;
2895 char crypted
[MD5_CRYPT_LENGTH
+1];
2900 NICKSERV_MIN_PARMS(3);
2901 hi
= user
->handle_info
;
2905 if (!is_secure_password(hi
->handle
, new_pass
, user
)) return 0;
2908 if(nickserv_conf
.ldap_enable
) {
2909 ldap_result
= ldap_check_auth(hi
->handle
, old_pass
);
2910 if(ldap_result
!= LDAP_SUCCESS
) {
2911 if(ldap_result
== LDAP_INVALID_CREDENTIALS
)
2912 reply("NSMSG_PASSWORD_INVALID");
2914 reply("NSMSG_LDAP_FAIL", ldap_err2string(ldap_result
));
2919 if (!checkpass(old_pass
, hi
->passwd
)) {
2920 argv
[1] = "BADPASS";
2921 reply("NSMSG_PASSWORD_INVALID");
2924 cryptpass(new_pass
, crypted
);
2926 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
2928 if((rc
= ldap_do_modify(hi
->handle
, crypted
, NULL
)) != LDAP_SUCCESS
) {
2929 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
2934 //cryptpass(new_pass, hi->passwd);
2935 strcpy(hi
->passwd
, crypted
);
2936 if (nickserv_conf
.sync_log
)
2937 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
2939 reply("NSMSG_PASS_SUCCESS");
2944 nickserv_addmask(struct userNode
*user
, struct handle_info
*hi
, const char *mask
)
2947 char *new_mask
= canonicalize_hostmask(strdup(mask
));
2948 for (i
=0; i
<hi
->masks
->used
; i
++) {
2949 if (!irccasecmp(new_mask
, hi
->masks
->list
[i
])) {
2950 send_message(user
, nickserv
, "NSMSG_ADDMASK_ALREADY", new_mask
);
2955 string_list_append(hi
->masks
, new_mask
);
2956 send_message(user
, nickserv
, "NSMSG_ADDMASK_SUCCESS", new_mask
);
2960 static NICKSERV_FUNC(cmd_addmask
)
2963 char *mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
2964 int res
= nickserv_addmask(user
, user
->handle_info
, mask
);
2968 if (!is_gline(argv
[1])) {
2969 reply("NSMSG_MASK_INVALID", argv
[1]);
2972 return nickserv_addmask(user
, user
->handle_info
, argv
[1]);
2976 static NICKSERV_FUNC(cmd_oaddmask
)
2978 struct handle_info
*hi
;
2980 NICKSERV_MIN_PARMS(3);
2981 if (!(hi
= get_victim_oper(user
, argv
[1])))
2983 return nickserv_addmask(user
, hi
, argv
[2]);
2987 nickserv_delmask(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, const char *del_mask
, int force
)
2990 for (i
=0; i
<hi
->masks
->used
; i
++) {
2991 if (!strcmp(del_mask
, hi
->masks
->list
[i
])) {
2992 char *old_mask
= hi
->masks
->list
[i
];
2993 if (hi
->masks
->used
== 1 && !force
) {
2994 reply("NSMSG_DELMASK_NOTLAST");
2997 hi
->masks
->list
[i
] = hi
->masks
->list
[--hi
->masks
->used
];
2998 reply("NSMSG_DELMASK_SUCCESS", old_mask
);
3003 reply("NSMSG_DELMASK_NOT_FOUND");
3007 static NICKSERV_FUNC(cmd_delmask
)
3009 NICKSERV_MIN_PARMS(2);
3010 return nickserv_delmask(cmd
, user
, user
->handle_info
, argv
[1], 0);
3013 static NICKSERV_FUNC(cmd_odelmask
)
3015 struct handle_info
*hi
;
3016 NICKSERV_MIN_PARMS(3);
3017 if (!(hi
= get_victim_oper(user
, argv
[1])))
3019 return nickserv_delmask(cmd
, user
, hi
, argv
[2], 1);
3023 nickserv_addsslfp(struct userNode
*user
, struct handle_info
*hi
, const char *sslfp
)
3026 char *new_sslfp
= strdup(sslfp
);
3027 for (i
=0; i
<hi
->sslfps
->used
; i
++) {
3028 if (!irccasecmp(new_sslfp
, hi
->sslfps
->list
[i
])) {
3029 send_message(user
, nickserv
, "NSMSG_ADDSSLFP_ALREADY", new_sslfp
);
3034 string_list_append(hi
->sslfps
, new_sslfp
);
3035 send_message(user
, nickserv
, "NSMSG_ADDSSLFP_SUCCESS", new_sslfp
);
3039 static NICKSERV_FUNC(cmd_addsslfp
)
3041 NICKSERV_MIN_PARMS((user
->sslfp
? 1 : 2));
3042 if ((argc
< 2) && (user
->sslfp
)) {
3043 int res
= nickserv_addsslfp(user
, user
->handle_info
, user
->sslfp
);
3046 return nickserv_addsslfp(user
, user
->handle_info
, argv
[1]);
3050 static NICKSERV_FUNC(cmd_oaddsslfp
)
3052 struct handle_info
*hi
;
3054 NICKSERV_MIN_PARMS(3);
3055 if (!(hi
= get_victim_oper(user
, argv
[1])))
3057 return nickserv_addsslfp(user
, hi
, argv
[2]);
3061 nickserv_delsslfp(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, const char *del_sslfp
)
3064 for (i
=0; i
<hi
->sslfps
->used
; i
++) {
3065 if (!irccasecmp(del_sslfp
, hi
->sslfps
->list
[i
])) {
3066 char *old_sslfp
= hi
->sslfps
->list
[i
];
3067 hi
->sslfps
->list
[i
] = hi
->sslfps
->list
[--hi
->sslfps
->used
];
3068 reply("NSMSG_DELSSLFP_SUCCESS", old_sslfp
);
3073 reply("NSMSG_DELSSLFP_NOT_FOUND");
3077 static NICKSERV_FUNC(cmd_delsslfp
)
3079 NICKSERV_MIN_PARMS((user
->sslfp
? 1 : 2));
3080 if ((argc
< 2) && (user
->sslfp
)) {
3081 return nickserv_delsslfp(cmd
, user
, user
->handle_info
, user
->sslfp
);
3083 return nickserv_delsslfp(cmd
, user
, user
->handle_info
, argv
[1]);
3087 static NICKSERV_FUNC(cmd_odelsslfp
)
3089 struct handle_info
*hi
;
3090 NICKSERV_MIN_PARMS(3);
3091 if (!(hi
= get_victim_oper(user
, argv
[1])))
3093 return nickserv_delsslfp(cmd
, user
, hi
, argv
[2]);
3097 nickserv_modify_handle_flags(struct userNode
*user
, struct userNode
*bot
, const char *str
, unsigned long *padded
, unsigned long *premoved
) {
3098 unsigned int nn
, add
= 1, pos
;
3099 unsigned long added
, removed
, flag
;
3101 for (added
=removed
=nn
=0; str
[nn
]; nn
++) {
3103 case '+': add
= 1; break;
3104 case '-': add
= 0; break;
3106 if (!(pos
= handle_inverse_flags
[(unsigned char)str
[nn
]])) {
3107 send_message(user
, bot
, "NSMSG_INVALID_FLAG", str
[nn
]);
3110 if (user
&& (user
->handle_info
->opserv_level
< flag_access_levels
[pos
-1])) {
3111 /* cheesy avoidance of looking up the flag name.. */
3112 send_message(user
, bot
, "NSMSG_FLAG_PRIVILEGED", str
[nn
]);
3115 flag
= 1 << (pos
- 1);
3117 added
|= flag
, removed
&= ~flag
;
3119 removed
|= flag
, added
&= ~flag
;
3124 *premoved
= removed
;
3129 nickserv_apply_flags(struct userNode
*user
, struct handle_info
*hi
, const char *flags
)
3131 unsigned long before
, after
, added
, removed
;
3132 struct userNode
*uNode
;
3134 before
= hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
);
3135 if (!nickserv_modify_handle_flags(user
, nickserv
, flags
, &added
, &removed
))
3137 hi
->flags
= (hi
->flags
| added
) & ~removed
;
3138 after
= hi
->flags
& (HI_FLAG_SUPPORT_HELPER
|HI_FLAG_NETWORK_HELPER
);
3140 /* Strip helping flag if they're only a support helper and not
3141 * currently in #support. */
3142 if (HANDLE_FLAGGED(hi
, HELPING
) && (after
== HI_FLAG_SUPPORT_HELPER
)) {
3143 struct channelList
*schannels
;
3145 schannels
= chanserv_support_channels();
3146 for (ii
= 0; ii
< schannels
->used
; ++ii
)
3147 if (find_handle_in_channel(schannels
->list
[ii
], hi
, NULL
))
3149 if (ii
== schannels
->used
)
3150 HANDLE_CLEAR_FLAG(hi
, HELPING
);
3153 if (after
&& !before
) {
3154 /* Add user to current helper list. */
3155 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
3156 userList_append(&curr_helpers
, uNode
);
3157 } else if (!after
&& before
) {
3158 /* Remove user from current helper list. */
3159 for (uNode
= hi
->users
; uNode
; uNode
= uNode
->next_authed
)
3160 userList_remove(&curr_helpers
, uNode
);
3167 set_list(struct svccmd
*cmd
, struct userNode
*user
, struct handle_info
*hi
, int override
)
3171 char *set_display
[] = {
3172 "INFO", "WIDTH", "TABLEWIDTH", "COLOR", "PRIVMSG", "STYLE",
3173 "EMAIL", "ANNOUNCEMENTS", "AUTOHIDE", "MAXLOGINS", "LANGUAGE",
3174 "FAKEHOST", "TITLE", "EPITHET", "ADVANCED"
3177 reply("NSMSG_SETTING_LIST");
3178 reply("NSMSG_SETTING_LIST_HEADER");
3180 /* Do this so options are presented in a consistent order. */
3181 for (i
= 0; i
< ArrayLength(set_display
); ++i
)
3182 if ((opt
= dict_find(nickserv_opt_dict
, set_display
[i
], NULL
)))
3183 opt(cmd
, user
, hi
, override
, 0, 0, NULL
);
3184 reply("NSMSG_SETTING_LIST_END");
3187 static NICKSERV_FUNC(cmd_set
)
3189 struct handle_info
*hi
;
3192 hi
= user
->handle_info
;
3194 set_list(cmd
, user
, hi
, 0);
3197 if (!(opt
= dict_find(nickserv_opt_dict
, argv
[1], NULL
))) {
3198 reply("NSMSG_INVALID_OPTION", argv
[1]);
3201 return opt(cmd
, user
, hi
, 0, 0, argc
-1, argv
+1);
3204 static NICKSERV_FUNC(cmd_oset
)
3206 struct handle_info
*hi
;
3209 NICKSERV_MIN_PARMS(2);
3211 if (!(hi
= get_victim_oper(user
, argv
[1])))
3215 set_list(cmd
, user
, hi
, 0);
3219 if (!(opt
= dict_find(nickserv_opt_dict
, argv
[2], NULL
))) {
3220 reply("NSMSG_INVALID_OPTION", argv
[2]);
3224 return opt(cmd
, user
, hi
, 1, 0, argc
-2, argv
+2);
3227 static OPTION_FUNC(opt_info
)
3231 if ((argv
[1][0] == '*') && (argv
[1][1] == 0)) {
3233 hi
->infoline
= NULL
;
3235 hi
->infoline
= strdup(unsplit_string(argv
+1, argc
-1, NULL
));
3239 info
= hi
->infoline
? hi
->infoline
: user_find_message(user
, "MSG_NONE");
3241 reply("NSMSG_SET_INFO", info
);
3245 static OPTION_FUNC(opt_width
)
3248 hi
->screen_width
= strtoul(argv
[1], NULL
, 0);
3250 if ((hi
->screen_width
> 0) && (hi
->screen_width
< MIN_LINE_SIZE
))
3251 hi
->screen_width
= MIN_LINE_SIZE
;
3252 else if (hi
->screen_width
> MAX_LINE_SIZE
)
3253 hi
->screen_width
= MAX_LINE_SIZE
;
3256 reply("NSMSG_SET_WIDTH", hi
->screen_width
);
3260 static OPTION_FUNC(opt_tablewidth
)
3263 hi
->table_width
= strtoul(argv
[1], NULL
, 0);
3265 if ((hi
->table_width
> 0) && (hi
->table_width
< MIN_LINE_SIZE
))
3266 hi
->table_width
= MIN_LINE_SIZE
;
3267 else if (hi
->screen_width
> MAX_LINE_SIZE
)
3268 hi
->table_width
= MAX_LINE_SIZE
;
3271 reply("NSMSG_SET_TABLEWIDTH", hi
->table_width
);
3275 static OPTION_FUNC(opt_color
)
3278 if (enabled_string(argv
[1]))
3279 HANDLE_SET_FLAG(hi
, MIRC_COLOR
);
3280 else if (disabled_string(argv
[1]))
3281 HANDLE_CLEAR_FLAG(hi
, MIRC_COLOR
);
3284 reply("MSG_INVALID_BINARY", argv
[1]);
3290 reply("NSMSG_SET_COLOR", user_find_message(user
, HANDLE_FLAGGED(hi
, MIRC_COLOR
) ? "MSG_ON" : "MSG_OFF"));
3294 static OPTION_FUNC(opt_privmsg
)
3297 if (enabled_string(argv
[1]))
3298 HANDLE_SET_FLAG(hi
, USE_PRIVMSG
);
3299 else if (disabled_string(argv
[1]))
3300 HANDLE_CLEAR_FLAG(hi
, USE_PRIVMSG
);
3303 reply("MSG_INVALID_BINARY", argv
[1]);
3309 reply("NSMSG_SET_PRIVMSG", user_find_message(user
, HANDLE_FLAGGED(hi
, USE_PRIVMSG
) ? "MSG_ON" : "MSG_OFF"));
3313 static OPTION_FUNC(opt_autohide
)
3316 if (enabled_string(argv
[1]))
3317 HANDLE_SET_FLAG(hi
, AUTOHIDE
);
3318 else if (disabled_string(argv
[1]))
3319 HANDLE_CLEAR_FLAG(hi
, AUTOHIDE
);
3322 reply("MSG_INVALID_BINARY", argv
[1]);
3328 reply("NSMSG_SET_AUTOHIDE", user_find_message(user
, HANDLE_FLAGGED(hi
, AUTOHIDE
) ? "MSG_ON" : "MSG_OFF"));
3332 static OPTION_FUNC(opt_style
)
3337 if (!irccasecmp(argv
[1], "Clean"))
3338 hi
->userlist_style
= HI_STYLE_CLEAN
;
3339 else if (!irccasecmp(argv
[1], "Advanced"))
3340 hi
->userlist_style
= HI_STYLE_ADVANCED
;
3341 else if (!irccasecmp(argv
[1], "Classic"))
3342 hi
->userlist_style
= HI_STYLE_CLASSIC
;
3343 else /* Default to normal */
3344 hi
->userlist_style
= HI_STYLE_NORMAL
;
3345 } /* TODO: give error if unknow style is chosen */
3347 switch (hi
->userlist_style
) {
3348 case HI_STYLE_ADVANCED
:
3351 case HI_STYLE_CLASSIC
:
3354 case HI_STYLE_CLEAN
:
3357 case HI_STYLE_NORMAL
:
3363 reply("NSMSG_SET_STYLE", style
);
3367 static OPTION_FUNC(opt_announcements
)
3372 if (enabled_string(argv
[1]))
3373 hi
->announcements
= 'y';
3374 else if (disabled_string(argv
[1]))
3375 hi
->announcements
= 'n';
3376 else if (!strcmp(argv
[1], "?") || !irccasecmp(argv
[1], "default"))
3377 hi
->announcements
= '?';
3380 reply("NSMSG_INVALID_ANNOUNCE", argv
[1]);
3385 switch (hi
->announcements
) {
3386 case 'y': choice
= user_find_message(user
, "MSG_ON"); break;
3387 case 'n': choice
= user_find_message(user
, "MSG_OFF"); break;
3388 case '?': choice
= "default"; break;
3389 default: choice
= "unknown"; break;
3392 reply("NSMSG_SET_ANNOUNCEMENTS", choice
);
3396 static OPTION_FUNC(opt_password
)
3398 char crypted
[MD5_CRYPT_LENGTH
+1];
3404 reply("NSMSG_USE_CMD_PASS");
3408 cryptpass(argv
[1], crypted
);
3410 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
3412 if((rc
= ldap_do_modify(hi
->handle
, crypted
, NULL
)) != LDAP_SUCCESS
) {
3414 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3419 strcpy(hi
->passwd
, crypted
);
3420 if (nickserv_conf
.sync_log
)
3421 SyncLog("PASSCHANGE %s %s", hi
->handle
, hi
->passwd
);
3424 reply("NSMSG_SET_PASSWORD", "***");
3428 static OPTION_FUNC(opt_flags
)
3431 unsigned int ii
, flen
;
3435 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3440 nickserv_apply_flags(user
, hi
, argv
[1]);
3442 for (ii
= flen
= 0; handle_flags
[ii
]; ii
++)
3443 if (hi
->flags
& (1 << ii
))
3444 flags
[flen
++] = handle_flags
[ii
];
3448 reply("NSMSG_SET_FLAGS", flags
);
3450 reply("NSMSG_SET_FLAGS", user_find_message(user
, "MSG_NONE"));
3455 static OPTION_FUNC(opt_email
)
3459 if (!valid_email(argv
[1])) {
3461 reply("NSMSG_BAD_EMAIL_ADDR");
3464 if ((str
= mail_prohibited_address(argv
[1]))) {
3466 reply("NSMSG_EMAIL_PROHIBITED", argv
[1], str
);
3469 if (hi
->email_addr
&& !irccasecmp(hi
->email_addr
, argv
[1])) {
3471 reply("NSMSG_EMAIL_SAME");
3472 } else if (!override
)
3473 nickserv_make_cookie(user
, hi
, EMAIL_CHANGE
, argv
[1], 0);
3476 if(nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_admin_dn
) {
3478 if((rc
= ldap_do_modify(hi
->handle
, NULL
, argv
[1])) != LDAP_SUCCESS
) {
3480 reply("NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3485 nickserv_set_email_addr(hi
, argv
[1]);
3487 nickserv_eat_cookie(hi
->cookie
);
3489 reply("NSMSG_SET_EMAIL", visible_email_addr(user
, hi
));
3493 reply("NSMSG_SET_EMAIL", visible_email_addr(user
, hi
));
3498 static OPTION_FUNC(opt_maxlogins
)
3500 unsigned char maxlogins
;
3502 maxlogins
= strtoul(argv
[1], NULL
, 0);
3503 if ((maxlogins
> nickserv_conf
.hard_maxlogins
) && !override
) {
3505 reply("NSMSG_BAD_MAX_LOGINS", nickserv_conf
.hard_maxlogins
);
3508 hi
->maxlogins
= maxlogins
;
3510 maxlogins
= hi
->maxlogins
? hi
->maxlogins
: nickserv_conf
.default_maxlogins
;
3512 reply("NSMSG_SET_MAXLOGINS", maxlogins
);
3516 static OPTION_FUNC(opt_advanced
)
3519 if (enabled_string(argv
[1]))
3520 HANDLE_SET_FLAG(hi
, ADVANCED
);
3521 else if (disabled_string(argv
[1]))
3522 HANDLE_CLEAR_FLAG(hi
, ADVANCED
);
3525 reply("MSG_INVALID_BINARY", argv
[1]);
3531 reply("NSMSG_SET_ADVANCED", user_find_message(user
, HANDLE_FLAGGED(hi
, ADVANCED
) ? "MSG_ON" : "MSG_OFF"));
3535 static OPTION_FUNC(opt_language
)
3537 struct language
*lang
;
3539 lang
= language_find(argv
[1]);
3540 if (irccasecmp(lang
->name
, argv
[1])) {
3542 reply("NSMSG_LANGUAGE_NOT_FOUND", argv
[1], lang
->name
);
3544 hi
->language
= lang
;
3547 reply("NSMSG_SET_LANGUAGE", hi
->language
->name
);
3551 static OPTION_FUNC(opt_karma
)
3555 send_message(user
, nickserv
, "MSG_SETTING_PRIVILEGED", argv
[0]);
3560 if (argv
[1][0] == '+' && isdigit(argv
[1][1])) {
3561 hi
->karma
+= strtoul(argv
[1] + 1, NULL
, 10);
3562 } else if (argv
[1][0] == '-' && isdigit(argv
[1][1])) {
3563 hi
->karma
-= strtoul(argv
[1] + 1, NULL
, 10);
3566 send_message(user
, nickserv
, "NSMSG_INVALID_KARMA", argv
[1]);
3571 send_message(user
, nickserv
, "NSMSG_SET_KARMA", hi
->karma
);
3575 /* Called from opserv from cmd_access */
3577 oper_try_set_access(struct userNode
*user
, struct userNode
*bot
, struct handle_info
*target
, unsigned int new_level
) {
3578 if (!oper_has_access(user
, bot
, nickserv_conf
.modoper_level
, 0))
3580 if ((user
->handle_info
->opserv_level
< target
->opserv_level
)
3581 || ((user
->handle_info
->opserv_level
== target
->opserv_level
)
3582 && (user
->handle_info
->opserv_level
< 1000))) {
3583 send_message(user
, bot
, "MSG_USER_OUTRANKED", target
->handle
);
3586 if ((user
->handle_info
->opserv_level
< new_level
)
3587 || ((user
->handle_info
->opserv_level
== new_level
)
3588 && (user
->handle_info
->opserv_level
< 1000))) {
3589 send_message(user
, bot
, "NSMSG_OPSERV_LEVEL_BAD");
3592 if (user
->handle_info
== target
) {
3593 send_message(user
, bot
, "MSG_STUPID_ACCESS_CHANGE");
3597 if(nickserv_conf
.ldap_enable
&& *(nickserv_conf
.ldap_oper_group_dn
) && *(nickserv_conf
.ldap_admin_dn
)) {
3599 if(new_level
> nickserv_conf
.ldap_oper_group_level
)
3600 rc
= ldap_add2group(target
->handle
, nickserv_conf
.ldap_oper_group_dn
);
3602 rc
= ldap_delfromgroup(target
->handle
, nickserv_conf
.ldap_oper_group_dn
);
3603 if(rc
!= LDAP_SUCCESS
&& rc
!= LDAP_TYPE_OR_VALUE_EXISTS
&& rc
!= LDAP_NO_SUCH_ATTRIBUTE
) {
3604 send_message(user
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3608 if(nickserv_conf
.ldap_enable
&& *(nickserv_conf
.ldap_field_oslevel
) && *(nickserv_conf
.ldap_admin_dn
)) {
3610 if((rc
= ldap_do_oslevel(target
->handle
, new_level
, target
->opserv_level
)) != LDAP_SUCCESS
) {
3611 send_message(user
, bot
, "NSMSG_LDAP_FAIL", ldap_err2string(rc
));
3616 if (target
->opserv_level
== new_level
)
3618 log_module(NS_LOG
, LOG_INFO
, "Account %s setting oper level for account %s to %d (from %d).",
3619 user
->handle_info
->handle
, target
->handle
, new_level
, target
->opserv_level
);
3620 target
->opserv_level
= new_level
;
3624 static OPTION_FUNC(opt_level
)
3630 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3634 res
= (argc
> 1) ? oper_try_set_access(user
, nickserv
, hi
, strtoul(argv
[1], NULL
, 0)) : 0;
3636 reply("NSMSG_SET_LEVEL", hi
->opserv_level
);
3640 static OPTION_FUNC(opt_epithet
)
3642 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_epithet_level
, 0)) {
3644 struct userNode
*target
, *next_un
;
3648 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3652 epithet
= unsplit_string(argv
+1, argc
-1, NULL
);
3656 if ((epithet
[0] == '*') && !epithet
[1])
3659 hi
->epithet
= strdup(epithet
);
3661 for (target
= hi
->users
; target
; target
= next_un
) {
3662 irc_swhois(nickserv
, target
, hi
->epithet
);
3664 next_un
= target
->next_authed
;
3670 reply("NSMSG_SET_EPITHET", hi
->epithet
);
3672 reply("NSMSG_SET_EPITHET", user_find_message(user
, "MSG_NONE"));
3677 static OPTION_FUNC(opt_title
)
3680 const char *none
= NULL
;
3683 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_title_level
, 0)) {
3686 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3691 if(!strcmp(title
, "*")) {
3693 hi
->fakehost
= NULL
;
3696 if (strchr(title
, '.')) {
3698 reply("NSMSG_TITLE_INVALID");
3701 /* Alphanumeric titles only. */
3702 for(sptr
= title
; *sptr
; sptr
++) {
3703 if(!isalnum(*sptr
) && *sptr
!= '-') {
3705 reply("NSMSG_TITLE_INVALID");
3709 if ((strlen(user
->handle_info
->handle
) + strlen(title
) +
3710 strlen(nickserv_conf
.titlehost_suffix
) + 2) > HOSTLEN
) {
3712 reply("NSMSG_TITLE_TRUNCATED");
3716 hi
->fakehost
= malloc(strlen(title
)+2);
3717 hi
->fakehost
[0] = '.';
3718 strcpy(hi
->fakehost
+1, title
);
3721 } else if (hi
->fakehost
&& (hi
->fakehost
[0] == '.'))
3722 title
= hi
->fakehost
+ 1;
3724 /* If theres no title set then the default title will therefore
3725 be the first part of hidden_host in x3.conf, so for
3726 consistency with opt_fakehost we will print this here.
3727 This isnt actually used in P10, its just handled to keep from crashing... */
3728 char *hs
, *hidden_suffix
, *rest
;
3730 hs
= conf_get_data("server/hidden_host", RECDB_QSTRING
);
3731 hidden_suffix
= strdup(hs
);
3733 /* Yes we do this twice */
3734 if((rest
= strchr(hidden_suffix
, '.')))
3737 title
= hidden_suffix
;
3741 /* A lame default if someone configured hidden_host to something lame */
3742 title
= strdup("users");
3743 free(hidden_suffix
);
3749 none
= user_find_message(user
, "MSG_NONE");
3751 send_message(user
, nickserv
, "NSMSG_SET_TITLE", title
? title
: none
);
3756 check_vhost(char *vhost
, struct userNode
*user
, struct svccmd
*cmd
)
3760 // check for a dot in the vhost
3761 if(strchr(vhost
, '.') == NULL
) {
3762 reply("NSMSG_NOT_VALID_FAKEHOST_DOT", vhost
);
3766 // check for a @ in the vhost
3767 if(strchr(vhost
, '@') != NULL
) {
3768 reply("NSMSG_NOT_VALID_FAKEHOST_AT", vhost
);
3772 // check for denied words, inspired by monk at paki.sex
3773 for(y
= 0; y
< nickserv_conf
.denied_fakehost_words
->used
; y
++) {
3774 if(strstr(vhost
, nickserv_conf
.denied_fakehost_words
->list
[y
]) != NULL
) {
3775 reply("NSMSG_DENIED_FAKEHOST_WORD", vhost
, nickserv_conf
.denied_fakehost_words
->list
[y
]);
3780 // check for ircu's HOSTLEN length.
3781 if(strlen(vhost
) >= HOSTLEN
) {
3782 reply("NSMSG_NOT_VALID_FAKEHOST_LEN", vhost
);
3786 /* This can be handled by the regex now if desired.
3787 if (vhost[strspn(vhost, "0123456789.")]) {
3788 hostname = vhost + strlen(vhost);
3789 for (depth = 1; depth && (hostname > vhost); depth--) {
3791 while ((hostname > vhost) && (*hostname != '.')) hostname--;
3794 if (*hostname == '.') hostname++; * advance past last dot we saw *
3795 if(strlen(hostname) > 4) {
3796 reply("NSMSG_NOT_VALID_FAKEHOST_TLD_LEN", vhost);
3801 /* test either regex or as valid handle */
3802 if (nickserv_conf
.valid_fakehost_regex_set
) {
3803 int err
= regexec(&nickserv_conf
.valid_fakehost_regex
, vhost
, 0, 0, 0);
3806 buff
[regerror(err
, &nickserv_conf
.valid_fakehost_regex
, buff
, sizeof(buff
))] = 0;
3807 log_module(NS_LOG
, LOG_INFO
, "regexec error: %s (%d)", buff
, err
);
3809 if(err
== REG_NOMATCH
) {
3810 reply("NSMSG_NOT_VALID_FAKEHOST_REGEX", vhost
);
3819 static OPTION_FUNC(opt_fakehost
)
3823 if ((argc
> 1) && oper_has_access(user
, nickserv
, nickserv_conf
.set_fakehost_level
, 0)) {
3826 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3831 if ((strlen(fake
) > HOSTLEN
) || (fake
[0] == '.')) {
3833 reply("NSMSG_FAKEHOST_INVALID", HOSTLEN
);
3836 if (!strcmp(fake
, "*")) {
3839 hi
->fakehost
= NULL
;
3842 else if (!check_vhost(argv
[1], user
, cmd
)) {
3843 /* check_vhost takes care of error reply */
3849 hi
->fakehost
= strdup(fake
);
3852 fake
= hi
->fakehost
;
3854 fake
= generate_fakehost(hi
);
3856 /* Tell them we set the host */
3858 fake
= user_find_message(user
, "MSG_NONE");
3860 reply("NSMSG_SET_FAKEHOST", fake
);
3864 static OPTION_FUNC(opt_note
)
3868 reply("MSG_SETTING_PRIVILEGED", argv
[0]);
3873 char *text
= unsplit_string(argv
+ 1, argc
- 1, NULL
);
3878 if ((text
[0] == '*') && !text
[1])
3881 if (!(hi
->note
= nickserv_add_note(user
->handle_info
->handle
, now
, text
)))
3887 reply("NSMSG_SET_NOTE", hi
->note
? hi
->note
->note
: user_find_message(user
, "MSG_NONE"));
3891 static NICKSERV_FUNC(cmd_reclaim
)
3893 struct handle_info
*hi
;
3894 struct nick_info
*ni
;
3895 struct userNode
*victim
;
3897 NICKSERV_MIN_PARMS(2);
3898 hi
= user
->handle_info
;
3899 ni
= dict_find(nickserv_nick_dict
, argv
[1], 0);
3901 reply("NSMSG_UNKNOWN_NICK", argv
[1]);
3904 if (ni
->owner
!= user
->handle_info
) {
3905 reply("NSMSG_NOT_YOUR_NICK", ni
->nick
);
3908 victim
= GetUserH(ni
->nick
);
3910 reply("MSG_NICK_UNKNOWN", ni
->nick
);
3913 if (victim
== user
) {
3914 reply("NSMSG_NICK_USER_YOU");
3917 nickserv_reclaim(victim
, ni
, nickserv_conf
.reclaim_action
);
3918 switch (nickserv_conf
.reclaim_action
) {
3919 case RECLAIM_NONE
: reply("NSMSG_RECLAIMED_NONE"); break;
3920 case RECLAIM_WARN
: reply("NSMSG_RECLAIMED_WARN", victim
->nick
); break;
3921 case RECLAIM_SVSNICK
: reply("NSMSG_RECLAIMED_SVSNICK", victim
->nick
); break;
3922 case RECLAIM_KILL
: reply("NSMSG_RECLAIMED_KILL", victim
->nick
); break;
3927 static NICKSERV_FUNC(cmd_unregnick
)
3930 struct handle_info
*hi
;
3931 struct nick_info
*ni
;
3933 hi
= user
->handle_info
;
3934 nick
= (argc
< 2) ? user
->nick
: (const char*)argv
[1];
3935 ni
= dict_find(nickserv_nick_dict
, nick
, NULL
);
3937 reply("NSMSG_UNKNOWN_NICK", nick
);
3940 if (hi
!= ni
->owner
) {
3941 reply("NSMSG_NOT_YOUR_NICK", nick
);
3944 reply("NSMSG_UNREGNICK_SUCCESS", ni
->nick
);
3949 static NICKSERV_FUNC(cmd_ounregnick
)
3951 struct nick_info
*ni
;
3953 NICKSERV_MIN_PARMS(2);
3954 if (!(ni
= get_nick_info(argv
[1]))) {
3955 reply("NSMSG_NICK_NOT_REGISTERED", argv
[1]);
3958 if (!oper_outranks(user
, ni
->owner
))
3960 reply("NSMSG_UNREGNICK_SUCCESS", ni
->nick
);
3965 static NICKSERV_FUNC(cmd_unregister
)
3967 struct handle_info
*hi
;
3970 NICKSERV_MIN_PARMS(2);
3971 hi
= user
->handle_info
;
3974 if (checkpass(passwd
, hi
->passwd
)) {
3975 if(nickserv_unregister_handle(hi
, user
, cmd
->parent
->bot
))
3980 log_module(NS_LOG
, LOG_INFO
, "Account '%s' tried to unregister with the wrong password.", hi
->handle
);
3981 reply("NSMSG_PASSWORD_INVALID");
3986 static NICKSERV_FUNC(cmd_ounregister
)
3988 struct handle_info
*hi
;
3989 char reason
[MAXLEN
];
3992 NICKSERV_MIN_PARMS(2);
3993 if (!(hi
= get_victim_oper(user
, argv
[1])))
3996 if (HANDLE_FLAGGED(hi
, NODELETE
)) {
3997 reply("NSMSG_UNREGISTER_NODELETE", hi
->handle
);
4001 force
= IsOper(user
) && (argc
> 2) && !irccasecmp(argv
[2], "force");
4003 ((hi
->flags
& nickserv_conf
.ounregister_flags
)
4005 || (hi
->last_quit_host
[0] && ((unsigned)(now
- hi
->lastseen
) < nickserv_conf
.ounregister_inactive
)))) {
4006 reply((IsOper(user
) ? "NSMSG_UNREGISTER_MUST_FORCE" : "NSMSG_UNREGISTER_CANNOT_FORCE"), hi
->handle
);
4009 snprintf(reason
, sizeof(reason
), "%s unregistered account %s.", user
->handle_info
->handle
, hi
->handle
);
4010 global_message(MESSAGE_RECIPIENT_STAFF
, reason
);
4011 if(nickserv_unregister_handle(hi
, user
, cmd
->parent
->bot
))
4017 static NICKSERV_FUNC(cmd_status
)
4019 if (nickserv_conf
.disable_nicks
) {
4020 reply("NSMSG_GLOBAL_STATS_NONICK",
4021 dict_size(nickserv_handle_dict
));
4023 if (user
->handle_info
) {
4025 struct nick_info
*ni
;
4026 for (ni
=user
->handle_info
->nicks
; ni
; ni
=ni
->next
) cnt
++;
4027 reply("NSMSG_HANDLE_STATS", cnt
);
4029 reply("NSMSG_HANDLE_NONE");
4031 reply("NSMSG_GLOBAL_STATS",
4032 dict_size(nickserv_handle_dict
),
4033 dict_size(nickserv_nick_dict
));
4038 static NICKSERV_FUNC(cmd_ghost
)
4040 struct userNode
*target
;
4041 char reason
[MAXLEN
];
4043 NICKSERV_MIN_PARMS(2);
4044 if (!(target
= GetUserH(argv
[1]))) {
4045 reply("MSG_NICK_UNKNOWN", argv
[1]);
4048 if (target
== user
) {
4049 reply("NSMSG_CANNOT_GHOST_SELF");
4052 if (!target
->handle_info
|| (target
->handle_info
!= user
->handle_info
)) {
4053 reply("NSMSG_CANNOT_GHOST_USER", target
->nick
);
4056 snprintf(reason
, sizeof(reason
), "Ghost kill on account %s (requested by %s).", target
->handle_info
->handle
, user
->nick
);
4057 DelUser(target
, nickserv
, 1, reason
);
4058 reply("NSMSG_GHOST_KILLED", argv
[1]);
4062 static NICKSERV_FUNC(cmd_vacation
)
4064 HANDLE_SET_FLAG(user
->handle_info
, FROZEN
);
4065 reply("NSMSG_ON_VACATION");
4070 nickserv_saxdb_write(struct saxdb_context
*ctx
) {
4072 struct handle_info
*hi
;
4075 for (it
= dict_first(nickserv_handle_dict
); it
; it
= iter_next(it
)) {
4077 saxdb_start_record(ctx
, iter_key(it
), 0);
4078 if (hi
->announcements
!= '?') {
4079 flags
[0] = hi
->announcements
;
4081 saxdb_write_string(ctx
, KEY_ANNOUNCEMENTS
, flags
);
4084 struct handle_cookie
*cookie
= hi
->cookie
;
4087 switch (cookie
->type
) {
4088 case ACTIVATION
: type
= KEY_ACTIVATION
; break;
4089 case PASSWORD_CHANGE
: type
= KEY_PASSWORD_CHANGE
; break;
4090 case EMAIL_CHANGE
: type
= KEY_EMAIL_CHANGE
; break;
4091 case ALLOWAUTH
: type
= KEY_ALLOWAUTH
; break;
4092 default: type
= NULL
; break;
4095 saxdb_start_record(ctx
, KEY_COOKIE
, 0);
4096 saxdb_write_string(ctx
, KEY_COOKIE_TYPE
, type
);
4097 saxdb_write_int(ctx
, KEY_COOKIE_EXPIRES
, cookie
->expires
);
4099 saxdb_write_string(ctx
, KEY_COOKIE_DATA
, cookie
->data
);
4100 saxdb_write_string(ctx
, KEY_COOKIE
, cookie
->cookie
);
4101 saxdb_end_record(ctx
);
4105 saxdb_write_string(ctx
, KEY_EMAIL_ADDR
, hi
->email_addr
);
4107 saxdb_write_string(ctx
, KEY_EPITHET
, hi
->epithet
);
4109 saxdb_start_record(ctx
, KEY_NOTE_NOTE
, 0);
4110 saxdb_write_string(ctx
, KEY_NOTE_SETTER
, hi
->note
->setter
);
4111 saxdb_write_int(ctx
, KEY_NOTE_DATE
, hi
->note
->date
);
4112 saxdb_write_string(ctx
, KEY_NOTE_NOTE
, hi
->note
->note
);
4113 saxdb_end_record(ctx
);
4117 saxdb_write_string(ctx
, KEY_FAKEHOST
, hi
->fakehost
);
4121 for (ii
=flen
=0; handle_flags
[ii
]; ++ii
)
4122 if (hi
->flags
& (1 << ii
))
4123 flags
[flen
++] = handle_flags
[ii
];
4125 saxdb_write_string(ctx
, KEY_FLAGS
, flags
);
4128 saxdb_write_string(ctx
, KEY_INFO
, hi
->infoline
);
4129 if (hi
->last_quit_host
[0])
4130 saxdb_write_string(ctx
, KEY_LAST_QUIT_HOST
, hi
->last_quit_host
);
4131 saxdb_write_int(ctx
, KEY_LAST_SEEN
, hi
->lastseen
);
4133 saxdb_write_sint(ctx
, KEY_KARMA
, hi
->karma
);
4134 if (hi
->masks
->used
)
4135 saxdb_write_string_list(ctx
, KEY_MASKS
, hi
->masks
);
4136 if (hi
->sslfps
->used
)
4137 saxdb_write_string_list(ctx
, KEY_SSLFPS
, hi
->sslfps
);
4138 if (hi
->ignores
->used
)
4139 saxdb_write_string_list(ctx
, KEY_IGNORES
, hi
->ignores
);
4141 saxdb_write_int(ctx
, KEY_MAXLOGINS
, hi
->maxlogins
);
4143 struct nick_info
*ni
;
4145 saxdb_start_record(ctx
, KEY_NICKS_EX
, 0);
4146 for (ni
= hi
->nicks
; ni
; ni
= ni
->next
) {
4147 saxdb_start_record(ctx
, ni
->nick
, 0);
4148 saxdb_write_int(ctx
, KEY_REGISTER_ON
, ni
->registered
);
4149 saxdb_write_int(ctx
, KEY_LAST_SEEN
, ni
->lastseen
);
4150 saxdb_end_record(ctx
);
4152 saxdb_end_record(ctx
);
4154 if (hi
->opserv_level
)
4155 saxdb_write_int(ctx
, KEY_OPSERV_LEVEL
, hi
->opserv_level
);
4156 if (hi
->language
!= lang_C
)
4157 saxdb_write_string(ctx
, KEY_LANGUAGE
, hi
->language
->name
);
4158 saxdb_write_string(ctx
, KEY_PASSWD
, hi
->passwd
);
4159 saxdb_write_int(ctx
, KEY_REGISTER_ON
, hi
->registered
);
4160 if (hi
->screen_width
)
4161 saxdb_write_int(ctx
, KEY_SCREEN_WIDTH
, hi
->screen_width
);
4162 if (hi
->table_width
)
4163 saxdb_write_int(ctx
, KEY_TABLE_WIDTH
, hi
->table_width
);
4164 flags
[0] = hi
->userlist_style
;
4166 saxdb_write_string(ctx
, KEY_USERLIST_STYLE
, flags
);
4167 saxdb_end_record(ctx
);
4173 static handle_merge_func_t
*handle_merge_func_list
;
4174 static void **handle_merge_func_list_extra
;
4175 static unsigned int handle_merge_func_size
= 0, handle_merge_func_used
= 0;
4178 reg_handle_merge_func(handle_merge_func_t func
, void *extra
)
4180 if (handle_merge_func_used
== handle_merge_func_size
) {
4181 if (handle_merge_func_size
) {
4182 handle_merge_func_size
<<= 1;
4183 handle_merge_func_list
= realloc(handle_merge_func_list
, handle_merge_func_size
*sizeof(handle_merge_func_t
));
4184 handle_merge_func_list_extra
= realloc(handle_merge_func_list_extra
, handle_merge_func_size
*sizeof(void*));
4186 handle_merge_func_size
= 8;
4187 handle_merge_func_list
= malloc(handle_merge_func_size
*sizeof(handle_merge_func_t
));
4188 handle_merge_func_list_extra
= malloc(handle_merge_func_size
*sizeof(void*));
4191 handle_merge_func_list
[handle_merge_func_used
] = func
;
4192 handle_merge_func_list_extra
[handle_merge_func_used
++] = extra
;
4195 static NICKSERV_FUNC(cmd_merge
)
4197 struct handle_info
*hi_from
, *hi_to
;
4198 struct userNode
*last_user
;
4199 struct userData
*cList
, *cListNext
;
4200 unsigned int ii
, jj
, n
;
4202 NICKSERV_MIN_PARMS(3);
4204 if (!(hi_from
= get_victim_oper(user
, argv
[1])))
4206 if (!(hi_to
= get_victim_oper(user
, argv
[2])))
4208 if (hi_to
== hi_from
) {
4209 reply("NSMSG_CANNOT_MERGE_SELF", hi_to
->handle
);
4213 for (n
=0; n
<handle_merge_func_used
; n
++)
4214 handle_merge_func_list
[n
](user
, hi_to
, hi_from
, handle_merge_func_list_extra
[n
]);
4216 /* Append "from" handle's nicks to "to" handle's nick list. */
4218 struct nick_info
*last_ni
;
4219 for (last_ni
=hi_to
->nicks
; last_ni
->next
; last_ni
=last_ni
->next
) ;
4220 last_ni
->next
= hi_from
->nicks
;
4222 while (hi_from
->nicks
) {
4223 hi_from
->nicks
->owner
= hi_to
;
4224 hi_from
->nicks
= hi_from
->nicks
->next
;
4227 /* Merge the hostmasks. */
4228 for (ii
=0; ii
<hi_from
->masks
->used
; ii
++) {
4229 char *mask
= hi_from
->masks
->list
[ii
];
4230 for (jj
=0; jj
<hi_to
->masks
->used
; jj
++)
4231 if (match_ircglobs(hi_to
->masks
->list
[jj
], mask
))
4233 if (jj
==hi_to
->masks
->used
) /* Nothing from the "to" handle covered this mask, so add it. */
4234 string_list_append(hi_to
->masks
, strdup(mask
));
4237 /* Merge the SSL fingerprints. */
4238 for (ii
=0; ii
<hi_from
->sslfps
->used
; ii
++) {
4239 char *sslfp
= hi_from
->sslfps
->list
[ii
];
4240 for (jj
=0; jj
<hi_to
->sslfps
->used
; jj
++)
4241 if (!irccasecmp(hi_to
->sslfps
->list
[jj
], sslfp
))
4243 if (jj
==hi_to
->sslfps
->used
) /* Nothing from the "to" handle covered this sslfp, so add it. */
4244 string_list_append(hi_to
->sslfps
, strdup(sslfp
));
4247 /* Merge the ignores. */
4248 for (ii
=0; ii
<hi_from
->ignores
->used
; ii
++) {
4249 char *ignore
= hi_from
->ignores
->list
[ii
];
4250 for (jj
=0; jj
<hi_to
->ignores
->used
; jj
++)
4251 if (match_ircglobs(hi_to
->ignores
->list
[jj
], ignore
))
4253 if (jj
==hi_to
->ignores
->used
) /* Nothing from the "to" handle covered this mask, so add it. */
4254 string_list_append(hi_to
->ignores
, strdup(ignore
));
4257 /* Merge the lists of authed users. */
4259 for (last_user
=hi_to
->users
; last_user
->next_authed
; last_user
=last_user
->next_authed
) ;
4260 last_user
->next_authed
= hi_from
->users
;
4262 hi_to
->users
= hi_from
->users
;
4264 /* Repoint the old "from" handle's users. */
4265 for (last_user
=hi_from
->users
; last_user
; last_user
=last_user
->next_authed
) {
4266 last_user
->handle_info
= hi_to
;
4268 hi_from
->users
= NULL
;
4270 /* Merge channel userlists. */
4271 for (cList
=hi_from
->channels
; cList
; cList
=cListNext
) {
4272 struct userData
*cList2
;
4273 cListNext
= cList
->u_next
;
4274 for (cList2
=hi_to
->channels
; cList2
; cList2
=cList2
->u_next
)
4275 if (cList
->channel
== cList2
->channel
)
4277 if (cList2
&& (cList2
->access
>= cList
->access
)) {
4278 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
);
4279 /* keep cList2 in hi_to; remove cList from hi_from */
4280 del_channel_user(cList
, 1);
4283 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
);
4284 /* remove the lower-ranking cList2 from hi_to */
4285 del_channel_user(cList2
, 1);
4287 log_module(NS_LOG
, LOG_INFO
, "Merge: %s had no access in %s", hi_to
->handle
, cList
->channel
->channel
->name
);
4289 /* cList needs to be moved from hi_from to hi_to */
4290 cList
->handle
= hi_to
;
4291 /* Remove from linked list for hi_from */
4292 assert(!cList
->u_prev
);
4293 hi_from
->channels
= cList
->u_next
;
4295 cList
->u_next
->u_prev
= cList
->u_prev
;
4296 /* Add to linked list for hi_to */
4297 cList
->u_prev
= NULL
;
4298 cList
->u_next
= hi_to
->channels
;
4299 if (hi_to
->channels
)
4300 hi_to
->channels
->u_prev
= cList
;
4301 hi_to
->channels
= cList
;
4305 /* Do they get an OpServ level promotion? */
4306 if (hi_from
->opserv_level
> hi_to
->opserv_level
)
4307 hi_to
->opserv_level
= hi_from
->opserv_level
;
4309 /* What about last seen time? */
4310 if (hi_from
->lastseen
> hi_to
->lastseen
)
4311 hi_to
->lastseen
= hi_from
->lastseen
;
4313 /* New karma is the sum of the two original karmas. */
4314 hi_to
->karma
+= hi_from
->karma
;
4316 /* Does a fakehost carry over? (This intentionally doesn't set it
4317 * for users previously attached to hi_to. They'll just have to
4320 if (hi_from
->fakehost
&& !hi_to
->fakehost
)
4321 hi_to
->fakehost
= strdup(hi_from
->fakehost
);
4323 /* Notify of success. */
4324 reply("NSMSG_HANDLES_MERGED", hi_from
->handle
, hi_to
->handle
);
4325 global_message_args(MESSAGE_RECIPIENT_OPERS
, "NSMSG_ACCOUNT_MERGED", user
->nick
,
4326 user
->handle_info
->handle
, hi_from
->handle
, hi_to
->handle
);
4328 /* Unregister the "from" handle. */
4329 nickserv_unregister_handle(hi_from
, NULL
, cmd
->parent
->bot
);
4330 /* TODO: fix it so that if the ldap delete in nickserv_unregister_handle fails,
4331 * the process isn't completed.
4337 struct nickserv_discrim
{
4338 unsigned long flags_on
, flags_off
;
4339 time_t min_registered
, max_registered
;
4342 int min_level
, max_level
;
4343 int min_karma
, max_karma
;
4344 enum { SUBSET
, EXACT
, SUPERSET
, LASTQUIT
} hostmask_type
;
4345 const char *nickmask
;
4346 const char *hostmask
;
4347 const char *handlemask
;
4348 const char *emailmask
;
4349 const char *titlemask
;
4350 const char *setwhat
;
4354 unsigned int inldap
;
4358 typedef void (*discrim_search_func
)(struct userNode
*source
, struct handle_info
*hi
, struct nickserv_discrim
*discrim
);
4360 struct discrim_apply_info
{
4361 struct nickserv_discrim
*discrim
;
4362 discrim_search_func func
;
4363 struct userNode
*source
;
4364 unsigned int matched
;
4367 static struct nickserv_discrim
*
4368 nickserv_discrim_create(struct svccmd
*cmd
, struct userNode
*user
, unsigned int argc
, char *argv
[])
4371 struct nickserv_discrim
*discrim
;
4373 discrim
= malloc(sizeof(*discrim
));
4374 memset(discrim
, 0, sizeof(*discrim
));
4375 discrim
->min_level
= 0;
4376 discrim
->max_level
= INT_MAX
;
4377 discrim
->limit
= 50;
4378 discrim
->min_registered
= 0;
4379 discrim
->max_registered
= INT_MAX
;
4380 discrim
->lastseen
= LONG_MAX
;
4381 discrim
->min_karma
= INT_MIN
;
4382 discrim
->max_karma
= INT_MAX
;
4385 discrim
->inldap
= 2;
4388 for (i
=0; i
<argc
; i
++) {
4389 if (i
== argc
- 1) {
4390 reply("MSG_MISSING_PARAMS", argv
[i
]);
4393 if (!irccasecmp(argv
[i
], "limit")) {
4394 discrim
->limit
= strtoul(argv
[++i
], NULL
, 0);
4395 } else if (!irccasecmp(argv
[i
], "flags")) {
4396 nickserv_modify_handle_flags(user
, nickserv
, argv
[++i
], &discrim
->flags_on
, &discrim
->flags_off
);
4397 } else if (!irccasecmp(argv
[i
], "registered")) {
4398 const char *cmp
= argv
[++i
];
4399 if (cmp
[0] == '<') {
4400 if (cmp
[1] == '=') {
4401 discrim
->min_registered
= now
- ParseInterval(cmp
+2);
4403 discrim
->min_registered
= now
- ParseInterval(cmp
+1) + 1;
4405 } else if (cmp
[0] == '=') {
4406 discrim
->min_registered
= discrim
->max_registered
= now
- ParseInterval(cmp
+1);
4407 } else if (cmp
[0] == '>') {
4408 if (cmp
[1] == '=') {
4409 discrim
->max_registered
= now
- ParseInterval(cmp
+2);
4411 discrim
->max_registered
= now
- ParseInterval(cmp
+1) - 1;
4414 reply("MSG_INVALID_CRITERIA", cmp
);
4416 } else if (!irccasecmp(argv
[i
], "seen")) {
4417 discrim
->lastseen
= now
- ParseInterval(argv
[++i
]);
4418 } else if (!nickserv_conf
.disable_nicks
&& !irccasecmp(argv
[i
], "nickmask")) {
4419 discrim
->nickmask
= argv
[++i
];
4420 } else if (!irccasecmp(argv
[i
], "setwhat")) {
4421 discrim
->setwhat
= argv
[++i
];
4422 if (!(dict_find(nickserv_opt_dict
, discrim
->setwhat
, NULL
))) {
4423 reply("NSMSG_INVALID_OPTION", discrim
->setwhat
);
4426 } else if (!irccasecmp(argv
[i
], "setvalue")) {
4427 discrim
->setval
= argv
[++i
];
4428 } else if (!irccasecmp(argv
[i
], "hostmask")) {
4430 if (!irccasecmp(argv
[i
], "exact")) {
4431 if (i
== argc
- 1) {
4432 reply("MSG_MISSING_PARAMS", argv
[i
]);
4435 discrim
->hostmask_type
= EXACT
;
4436 } else if (!irccasecmp(argv
[i
], "subset")) {
4437 if (i
== argc
- 1) {
4438 reply("MSG_MISSING_PARAMS", argv
[i
]);
4441 discrim
->hostmask_type
= SUBSET
;
4442 } else if (!irccasecmp(argv
[i
], "superset")) {
4443 if (i
== argc
- 1) {
4444 reply("MSG_MISSING_PARAMS", argv
[i
]);
4447 discrim
->hostmask_type
= SUPERSET
;
4448 } else if (!irccasecmp(argv
[i
], "lastquit") || !irccasecmp(argv
[i
], "lastauth")) {
4449 if (i
== argc
- 1) {
4450 reply("MSG_MISSING_PARAMS", argv
[i
]);
4453 discrim
->hostmask_type
= LASTQUIT
;
4456 discrim
->hostmask_type
= SUPERSET
;
4458 discrim
->hostmask
= argv
[++i
];
4459 } else if (!irccasecmp(argv
[i
], "handlemask") || !irccasecmp(argv
[i
], "accountmask") || !irccasecmp(argv
[i
], "account")) {
4460 if (!irccasecmp(argv
[++i
], "*")) {
4461 discrim
->handlemask
= 0;
4463 discrim
->handlemask
= argv
[i
];
4465 } else if (!irccasecmp(argv
[i
], "email")) {
4466 if (user
->handle_info
->opserv_level
< nickserv_conf
.email_search_level
) {
4467 reply("MSG_NO_SEARCH_ACCESS", "email");
4469 } else if (!irccasecmp(argv
[++i
], "*")) {
4470 discrim
->emailmask
= 0;
4472 discrim
->emailmask
= argv
[i
];
4474 } else if (!irccasecmp(argv
[i
], "title")) {
4475 if (!irccasecmp(argv
[++i
], "*")) {
4476 discrim
->titlemask
= 0;
4478 discrim
->titlemask
= argv
[i
];
4480 } else if (!irccasecmp(argv
[i
], "access")) {
4481 const char *cmp
= argv
[++i
];
4482 if (cmp
[0] == '<') {
4483 if (discrim
->min_level
== 0) discrim
->min_level
= 1;
4484 if (cmp
[1] == '=') {
4485 discrim
->max_level
= strtoul(cmp
+2, NULL
, 0);
4487 discrim
->max_level
= strtoul(cmp
+1, NULL
, 0) - 1;
4489 } else if (cmp
[0] == '=') {
4490 discrim
->min_level
= discrim
->max_level
= strtoul(cmp
+1, NULL
, 0);
4491 } else if (cmp
[0] == '>') {
4492 if (cmp
[1] == '=') {
4493 discrim
->min_level
= strtoul(cmp
+2, NULL
, 0);
4495 discrim
->min_level
= strtoul(cmp
+1, NULL
, 0) + 1;
4498 reply("MSG_INVALID_CRITERIA", cmp
);
4500 } else if (!irccasecmp(argv
[i
], "karma")) {
4501 const char *cmp
= argv
[++i
];
4502 if (cmp
[0] == '<') {
4503 if (cmp
[1] == '=') {
4504 discrim
->max_karma
= strtoul(cmp
+2, NULL
, 0);
4506 discrim
->max_karma
= strtoul(cmp
+1, NULL
, 0) - 1;
4508 } else if (cmp
[0] == '=') {
4509 discrim
->min_karma
= discrim
->max_karma
= strtoul(cmp
+1, NULL
, 0);
4510 } else if (cmp
[0] == '>') {
4511 if (cmp
[1] == '=') {
4512 discrim
->min_karma
= strtoul(cmp
+2, NULL
, 0);
4514 discrim
->min_karma
= strtoul(cmp
+1, NULL
, 0) + 1;
4517 send_message(user
, nickserv
, "MSG_INVALID_CRITERIA", cmp
);
4520 } else if (nickserv_conf
.ldap_enable
&& !irccasecmp(argv
[i
], "inldap")) {
4522 if(true_string(argv
[i
])) {
4523 discrim
->inldap
= 1;
4525 else if (false_string(argv
[i
])) {
4526 discrim
->inldap
= 0;
4529 reply("MSG_INVALID_BINARY", argv
[i
]);
4533 reply("MSG_INVALID_CRITERIA", argv
[i
]);
4544 nickserv_discrim_match(struct nickserv_discrim
*discrim
, struct handle_info
*hi
)
4548 if (hi
->fakehost
&& (hi
->fakehost
[0] == '.'))
4549 title
= hi
->fakehost
+ 1;
4551 if (((discrim
->flags_on
& hi
->flags
) != discrim
->flags_on
)
4552 || (discrim
->flags_off
& hi
->flags
)
4553 || (discrim
->min_registered
> hi
->registered
)
4554 || (discrim
->max_registered
< hi
->registered
)
4555 || (discrim
->lastseen
< (hi
->users
?now
:hi
->lastseen
))
4556 || (discrim
->handlemask
&& !match_ircglob(hi
->handle
, discrim
->handlemask
))
4557 || (discrim
->emailmask
&& (!hi
->email_addr
|| !match_ircglob(hi
->email_addr
, discrim
->emailmask
)))
4558 || (discrim
->titlemask
&& (!title
|| !match_ircglob(title
, discrim
->titlemask
)))
4559 || (discrim
->min_level
> hi
->opserv_level
)
4560 || (discrim
->max_level
< hi
->opserv_level
)
4561 || (discrim
->min_karma
> hi
->karma
)
4562 || (discrim
->max_karma
< hi
->karma
)
4566 if (discrim
->hostmask
) {
4568 for (i
=0; i
<hi
->masks
->used
; i
++) {
4569 const char *mask
= hi
->masks
->list
[i
];
4570 if ((discrim
->hostmask_type
== SUBSET
)
4571 && (match_ircglobs(discrim
->hostmask
, mask
))) break;
4572 else if ((discrim
->hostmask_type
== EXACT
)
4573 && !irccasecmp(discrim
->hostmask
, mask
)) break;
4574 else if ((discrim
->hostmask_type
== SUPERSET
)
4575 && (match_ircglobs(mask
, discrim
->hostmask
))) break;
4576 else if ((discrim
->hostmask_type
== LASTQUIT
)
4577 && (match_ircglobs(discrim
->hostmask
, hi
->last_quit_host
))) break;
4579 if (i
==hi
->masks
->used
) return 0;
4581 if (discrim
->nickmask
) {
4582 struct nick_info
*nick
= hi
->nicks
;
4584 if (match_ircglob(nick
->nick
, discrim
->nickmask
)) break;
4587 if (!nick
) return 0;
4590 if(nickserv_conf
.ldap_enable
&& discrim
->inldap
!= 2) {
4592 rc
= ldap_get_user_info(hi
->handle
, NULL
);
4593 if(discrim
->inldap
== 1 && rc
!= LDAP_SUCCESS
)
4595 if(discrim
->inldap
== 0 && rc
== LDAP_SUCCESS
)
4604 nickserv_discrim_search(struct nickserv_discrim
*discrim
, discrim_search_func dsf
, struct userNode
*source
)
4606 dict_iterator_t it
, next
;
4607 unsigned int matched
;
4609 for (it
= dict_first(nickserv_handle_dict
), matched
= 0;
4610 it
&& (matched
< discrim
->limit
);
4612 next
= iter_next(it
);
4613 if (nickserv_discrim_match(discrim
, iter_data(it
))) {
4614 dsf(source
, iter_data(it
), discrim
);
4622 search_print_func(struct userNode
*source
, struct handle_info
*match
, UNUSED_ARG(struct nickserv_discrim
*discrim
))
4624 send_message(source
, nickserv
, "NSMSG_SEARCH_MATCH", match
->handle
);
4628 search_count_func(UNUSED_ARG(struct userNode
*source
), UNUSED_ARG(struct handle_info
*match
), UNUSED_ARG(struct nickserv_discrim
*discrim
))
4633 search_unregister_func (struct userNode
*source
, struct handle_info
*match
, UNUSED_ARG(struct nickserv_discrim
*discrim
))
4635 if (oper_has_access(source
, nickserv
, match
->opserv_level
, 0))
4636 nickserv_unregister_handle(match
, source
, nickserv
); // XXX nickserv hard coded
4641 search_add2ldap_func (struct userNode
*source
, struct handle_info
*match
, UNUSED_ARG(struct nickserv_discrim
*discrim
))
4644 if(match
->email_addr
&& match
->passwd
&& match
->handle
) {
4645 rc
= ldap_do_add(match
->handle
, match
->passwd
, match
->email_addr
);
4646 if(rc
!= LDAP_SUCCESS
) {
4647 send_message(source
, nickserv
, "NSMSG_LDAP_FAIL_ADD", match
->handle
, ldap_err2string(rc
));
4654 search_set_func (struct userNode
*source
, struct handle_info
*match
, struct nickserv_discrim
*discrim
)
4659 if (!(opt
= dict_find(nickserv_opt_dict
, discrim
->setwhat
, NULL
))) {
4663 oargv
[0] = (char *)discrim
->setwhat
;
4664 oargv
[1] = (char *)discrim
->setval
;
4666 opt(discrim
->cmd
, source
, match
, 1, 1, 2, oargv
);
4670 nickserv_sort_accounts_by_access(const void *a
, const void *b
)
4672 const struct handle_info
*hi_a
= *(const struct handle_info
**)a
;
4673 const struct handle_info
*hi_b
= *(const struct handle_info
**)b
;
4674 if (hi_a
->opserv_level
!= hi_b
->opserv_level
)
4675 return hi_b
->opserv_level
- hi_a
->opserv_level
;
4676 return irccasecmp(hi_a
->handle
, hi_b
->handle
);
4680 nickserv_show_oper_accounts(struct userNode
*user
, struct svccmd
*cmd
)
4682 struct handle_info_list hil
;
4683 struct helpfile_table tbl
;
4688 memset(&hil
, 0, sizeof(hil
));
4689 for (it
= dict_first(nickserv_handle_dict
); it
; it
= iter_next(it
)) {
4690 struct handle_info
*hi
= iter_data(it
);
4691 if (hi
->opserv_level
)
4692 handle_info_list_append(&hil
, hi
);
4694 qsort(hil
.list
, hil
.used
, sizeof(hil
.list
[0]), nickserv_sort_accounts_by_access
);
4695 tbl
.length
= hil
.used
+ 1;
4697 tbl
.flags
= TABLE_NO_FREE
| TABLE_REPEAT_ROWS
| TABLE_REPEAT_HEADERS
;
4698 tbl
.contents
= malloc(tbl
.length
* sizeof(tbl
.contents
[0]));
4699 tbl
.contents
[0] = ary
= malloc(tbl
.width
* sizeof(ary
[0]));
4702 for (ii
= 0; ii
< hil
.used
; ) {
4703 ary
= malloc(tbl
.width
* sizeof(ary
[0]));
4704 ary
[0] = hil
.list
[ii
]->handle
;
4705 ary
[1] = strtab(hil
.list
[ii
]->opserv_level
);
4706 tbl
.contents
[++ii
] = ary
;
4708 table_send(cmd
->parent
->bot
, user
->nick
, 0, NULL
, tbl
);
4709 /*reply("MSG_MATCH_COUNT", hil.used); */
4710 for (ii
= 0; ii
< hil
.used
; ii
++)
4711 free(tbl
.contents
[ii
]);
4716 static NICKSERV_FUNC(cmd_search
)
4718 struct nickserv_discrim
*discrim
;
4719 discrim_search_func action
;
4720 struct svccmd
*subcmd
;
4721 unsigned int matches
;
4724 NICKSERV_MIN_PARMS(3);
4725 sprintf(buf
, "search %s", argv
[1]);
4726 subcmd
= dict_find(nickserv_service
->commands
, buf
, NULL
);
4727 if (!irccasecmp(argv
[1], "print"))
4728 action
= search_print_func
;
4729 else if (!irccasecmp(argv
[1], "count"))
4730 action
= search_count_func
;
4731 else if (!irccasecmp(argv
[1], "unregister"))
4732 action
= search_unregister_func
;
4733 else if (!irccasecmp(argv
[1], "set"))
4734 action
= search_set_func
;
4736 else if (nickserv_conf
.ldap_enable
&& !irccasecmp(argv
[1], "add2ldap"))
4737 action
= search_add2ldap_func
;
4740 reply("NSMSG_INVALID_ACTION", argv
[1]);
4744 if (subcmd
&& !svccmd_can_invoke(user
, nickserv
, subcmd
, NULL
, SVCCMD_NOISY
))
4747 discrim
= nickserv_discrim_create(cmd
, user
, argc
-2, argv
+2);
4751 if (action
== search_print_func
)
4752 reply("NSMSG_ACCOUNT_SEARCH_RESULTS");
4753 else if (action
== search_count_func
)
4754 discrim
->limit
= INT_MAX
;
4755 else if ((action
== search_set_func
) && (!(discrim
->setwhat
) || !(discrim
->setval
)))
4756 return reply("MSG_MISSING_PARAMS", argv
[1]);
4758 matches
= nickserv_discrim_search(discrim
, action
, user
);
4761 reply("MSG_MATCH_COUNT", matches
);
4763 reply("MSG_NO_MATCHES");
4769 static MODCMD_FUNC(cmd_checkpass
)
4771 struct handle_info
*hi
;
4773 NICKSERV_MIN_PARMS(3);
4774 if (!(hi
= get_handle_info(argv
[1]))) {
4775 reply("MSG_HANDLE_UNKNOWN", argv
[1]);
4778 if (checkpass(argv
[2], hi
->passwd
))
4779 reply("CHECKPASS_YES");
4781 reply("CHECKPASS_NO");
4786 static MODCMD_FUNC(cmd_checkemail
)
4788 struct handle_info
*hi
;
4790 NICKSERV_MIN_PARMS(3);
4791 if (!(hi
= modcmd_get_handle_info(user
, argv
[1]))) {
4794 if (!hi
->email_addr
)
4795 reply("CHECKEMAIL_NOT_SET");
4796 else if (!irccasecmp(argv
[2], hi
->email_addr
))
4797 reply("CHECKEMAIL_YES");
4799 reply("CHECKEMAIL_NO");
4804 nickserv_db_read_handle(char *handle
, dict_t obj
)
4807 struct string_list
*masks
, *sslfps
, *slist
, *ignores
;
4808 struct handle_info
*hi
;
4809 struct userNode
*authed_users
;
4810 struct userData
*channel_list
;
4813 unsigned long int id
;
4816 char *setter
, *note
;
4819 str
= database_get_data(obj
, KEY_ID
, RECDB_QSTRING
);
4820 id
= str
? strtoul(str
, NULL
, 0) : 0;
4821 str
= database_get_data(obj
, KEY_PASSWD
, RECDB_QSTRING
);
4823 log_module(NS_LOG
, LOG_WARNING
, "did not find a password for %s -- skipping user.", handle
);
4826 if ((hi
= get_handle_info(handle
))) {
4827 authed_users
= hi
->users
;
4828 channel_list
= hi
->channels
;
4830 hi
->channels
= NULL
;
4831 dict_remove(nickserv_handle_dict
, hi
->handle
);
4833 authed_users
= NULL
;
4834 channel_list
= NULL
;
4836 if(nickserv_conf
.force_handles_lowercase
)
4837 irc_strtolower(handle
);
4838 hi
= register_handle(handle
, str
, id
);
4840 hi
->users
= authed_users
;
4841 while (authed_users
) {
4842 authed_users
->handle_info
= hi
;
4843 authed_users
= authed_users
->next_authed
;
4846 hi
->channels
= channel_list
;
4847 masks
= database_get_data(obj
, KEY_MASKS
, RECDB_STRING_LIST
);
4848 hi
->masks
= masks
? string_list_copy(masks
) : alloc_string_list(1);
4849 sslfps
= database_get_data(obj
, KEY_SSLFPS
, RECDB_STRING_LIST
);
4850 hi
->sslfps
= sslfps
? string_list_copy(sslfps
) : alloc_string_list(1);
4851 ignores
= database_get_data(obj
, KEY_IGNORES
, RECDB_STRING_LIST
);
4852 hi
->ignores
= ignores
? string_list_copy(ignores
) : alloc_string_list(1);
4853 str
= database_get_data(obj
, KEY_MAXLOGINS
, RECDB_QSTRING
);
4854 hi
->maxlogins
= str
? strtoul(str
, NULL
, 0) : 0;
4855 str
= database_get_data(obj
, KEY_LANGUAGE
, RECDB_QSTRING
);
4856 hi
->language
= language_find(str
? str
: "C");
4857 str
= database_get_data(obj
, KEY_OPSERV_LEVEL
, RECDB_QSTRING
);
4858 hi
->opserv_level
= str
? strtoul(str
, NULL
, 0) : 0;
4859 str
= database_get_data(obj
, KEY_INFO
, RECDB_QSTRING
);
4861 hi
->infoline
= strdup(str
);
4862 str
= database_get_data(obj
, KEY_REGISTER_ON
, RECDB_QSTRING
);
4863 hi
->registered
= str
? (time_t)strtoul(str
, NULL
, 0) : now
;
4864 str
= database_get_data(obj
, KEY_LAST_SEEN
, RECDB_QSTRING
);
4865 hi
->lastseen
= str
? (time_t)strtoul(str
, NULL
, 0) : hi
->registered
;
4866 str
= database_get_data(obj
, KEY_KARMA
, RECDB_QSTRING
);
4867 hi
->karma
= str
? strtoul(str
, NULL
, 0) : 0;
4868 /* We want to read the nicks even if disable_nicks is set. This is so
4869 * that we don't lose the nick data entirely. */
4870 obj2
= database_get_data(obj
, KEY_NICKS_EX
, RECDB_OBJECT
);
4871 for(it
= dict_first(obj2
); it
; it
= iter_next(it
))
4873 struct record_data
*rd
= iter_data(it
);
4874 struct nick_info
* ni
;
4876 register_nick(iter_key(it
), hi
);
4877 ni
= get_nick_info(iter_key(it
));
4882 str
= database_get_data(rd
->d
.object
, KEY_REGISTER_ON
, RECDB_QSTRING
);
4883 ni
->registered
= str
? (time_t)strtoul(str
, NULL
, 0) : now
;
4884 str
= database_get_data(rd
->d
.object
, KEY_LAST_SEEN
, RECDB_QSTRING
);
4885 ni
->lastseen
= str
? (time_t)strtoul(str
, NULL
, 0) : ni
->registered
;
4888 slist
= database_get_data(obj
, KEY_NICKS
, RECDB_STRING_LIST
);
4890 for (ii
=0; ii
<slist
->used
; ii
++) {
4891 struct nick_info
* ni
;
4893 register_nick(slist
->list
[ii
], hi
);
4894 ni
= get_nick_info(slist
->list
[ii
]);
4899 ni
->registered
= hi
->registered
;
4900 ni
->lastseen
= ni
->registered
;
4904 str
= database_get_data(obj
, KEY_FLAGS
, RECDB_QSTRING
);
4906 for (ii
=0; str
[ii
]; ii
++)
4907 hi
->flags
|= 1 << (handle_inverse_flags
[(unsigned char)str
[ii
]] - 1);
4909 str
= database_get_data(obj
, KEY_USERLIST_STYLE
, RECDB_QSTRING
);
4910 hi
->userlist_style
= str
? str
[0] : HI_DEFAULT_STYLE
;
4911 str
= database_get_data(obj
, KEY_ANNOUNCEMENTS
, RECDB_QSTRING
);
4912 hi
->announcements
= str
? str
[0] : '?';
4913 str
= database_get_data(obj
, KEY_SCREEN_WIDTH
, RECDB_QSTRING
);
4914 hi
->screen_width
= str
? strtoul(str
, NULL
, 0) : 0;
4915 str
= database_get_data(obj
, KEY_TABLE_WIDTH
, RECDB_QSTRING
);
4916 hi
->table_width
= str
? strtoul(str
, NULL
, 0) : 0;
4917 str
= database_get_data(obj
, KEY_LAST_QUIT_HOST
, RECDB_QSTRING
);
4919 str
= database_get_data(obj
, KEY_LAST_AUTHED_HOST
, RECDB_QSTRING
);
4921 safestrncpy(hi
->last_quit_host
, str
, sizeof(hi
->last_quit_host
));
4922 str
= database_get_data(obj
, KEY_EMAIL_ADDR
, RECDB_QSTRING
);
4924 nickserv_set_email_addr(hi
, str
);
4925 str
= database_get_data(obj
, KEY_EPITHET
, RECDB_QSTRING
);
4927 hi
->epithet
= strdup(str
);
4928 subdb
= database_get_data(obj
, KEY_NOTE_NOTE
, RECDB_OBJECT
);
4930 setter
= database_get_data(subdb
, KEY_NOTE_SETTER
, RECDB_QSTRING
);
4931 str
= database_get_data(subdb
, KEY_NOTE_DATE
, RECDB_QSTRING
);
4932 date
= str
? (time_t)strtoul(str
, NULL
, 0) : now
;
4933 note
= database_get_data(subdb
, KEY_NOTE_NOTE
, RECDB_QSTRING
);
4934 if (setter
&& date
&& note
)
4936 if (!(hi
->note
= nickserv_add_note(setter
, date
, note
)))
4941 str
= database_get_data(obj
, KEY_FAKEHOST
, RECDB_QSTRING
);
4943 hi
->fakehost
= strdup(str
);
4945 subdb
= database_get_data(obj
, KEY_COOKIE
, RECDB_OBJECT
);
4947 const char *data
, *type
, *expires
, *cookie_str
;
4948 struct handle_cookie
*cookie
;
4950 cookie
= calloc(1, sizeof(*cookie
));
4951 type
= database_get_data(subdb
, KEY_COOKIE_TYPE
, RECDB_QSTRING
);
4952 data
= database_get_data(subdb
, KEY_COOKIE_DATA
, RECDB_QSTRING
);
4953 expires
= database_get_data(subdb
, KEY_COOKIE_EXPIRES
, RECDB_QSTRING
);
4954 cookie_str
= database_get_data(subdb
, KEY_COOKIE
, RECDB_QSTRING
);
4955 if (!type
|| !expires
|| !cookie_str
) {
4956 log_module(NS_LOG
, LOG_ERROR
, "Missing field(s) from cookie for account %s; dropping cookie.", hi
->handle
);
4959 if (!irccasecmp(type
, KEY_ACTIVATION
))
4960 cookie
->type
= ACTIVATION
;
4961 else if (!irccasecmp(type
, KEY_PASSWORD_CHANGE
))
4962 cookie
->type
= PASSWORD_CHANGE
;
4963 else if (!irccasecmp(type
, KEY_EMAIL_CHANGE
))
4964 cookie
->type
= EMAIL_CHANGE
;
4965 else if (!irccasecmp(type
, KEY_ALLOWAUTH
))
4966 cookie
->type
= ALLOWAUTH
;
4968 log_module(NS_LOG
, LOG_ERROR
, "Invalid cookie type %s for account %s; dropping cookie.", type
, handle
);
4971 cookie
->expires
= strtoul(expires
, NULL
, 0);
4972 if (cookie
->expires
< now
)
4975 cookie
->data
= strdup(data
);
4976 safestrncpy(cookie
->cookie
, cookie_str
, sizeof(cookie
->cookie
));
4980 nickserv_bake_cookie(cookie
);
4982 nickserv_free_cookie(cookie
);
4987 nickserv_saxdb_read(dict_t db
) {
4989 struct record_data
*rd
;
4992 for (it
=dict_first(db
); it
; it
=iter_next(it
)) {
4994 handle
= strdup(iter_key(it
));
4995 nickserv_db_read_handle(handle
, rd
->d
.object
);
5001 static NICKSERV_FUNC(cmd_mergedb
)
5003 struct timeval start
, stop
;
5006 NICKSERV_MIN_PARMS(2);
5007 gettimeofday(&start
, NULL
);
5008 if (!(db
= parse_database(argv
[1]))) {
5009 reply("NSMSG_DB_UNREADABLE", argv
[1]);
5012 nickserv_saxdb_read(db
);
5014 gettimeofday(&stop
, NULL
);
5015 stop
.tv_sec
-= start
.tv_sec
;
5016 stop
.tv_usec
-= start
.tv_usec
;
5017 if (stop
.tv_usec
< 0) {
5019 stop
.tv_usec
+= 1000000;
5021 reply("NSMSG_DB_MERGED", argv
[1], stop
.tv_sec
, stop
.tv_usec
/1000);
5026 expire_handles(UNUSED_ARG(void *data
))
5028 dict_iterator_t it
, next
;
5030 struct handle_info
*hi
;
5032 for (it
=dict_first(nickserv_handle_dict
); it
; it
=next
) {
5033 next
= iter_next(it
);
5035 if ((hi
->opserv_level
> 0)
5037 || HANDLE_FLAGGED(hi
, FROZEN
)
5038 || HANDLE_FLAGGED(hi
, NODELETE
)) {
5041 expiry
= hi
->channels
? nickserv_conf
.handle_expire_delay
: nickserv_conf
.nochan_handle_expire_delay
;
5042 if ((now
- hi
->lastseen
) > expiry
) {
5043 log_module(NS_LOG
, LOG_INFO
, "Expiring account %s for inactivity.", hi
->handle
);
5044 nickserv_unregister_handle(hi
, NULL
, NULL
);
5048 if (nickserv_conf
.handle_expire_frequency
)
5049 timeq_add(now
+ nickserv_conf
.handle_expire_frequency
, expire_handles
, NULL
);
5053 expire_nicks(UNUSED_ARG(void *data
))
5055 dict_iterator_t it
, next
;
5056 time_t expiry
= nickserv_conf
.nick_expire_delay
;
5057 struct nick_info
*ni
;
5058 struct userNode
*ui
;
5060 if (!(nickserv_conf
.expire_nicks
))
5063 for (it
=dict_first(nickserv_nick_dict
); it
; it
=next
) {
5064 next
= iter_next(it
);
5066 if ((ni
->owner
->opserv_level
> 0)
5067 || ((ui
= GetUserH(ni
->nick
)) && (ui
->handle_info
) && (ui
->handle_info
== ni
->owner
))
5068 || HANDLE_FLAGGED(ni
->owner
, FROZEN
)
5069 || HANDLE_FLAGGED(ni
->owner
, NODELETE
)) {
5072 if ((now
- ni
->lastseen
) > expiry
) {
5073 log_module(NS_LOG
, LOG_INFO
, "Expiring nick %s for inactivity.", ni
->nick
);
5078 if (nickserv_conf
.nick_expire_frequency
&& nickserv_conf
.expire_nicks
)
5079 timeq_add(now
+ nickserv_conf
.nick_expire_frequency
, expire_nicks
, NULL
);
5083 nickserv_load_dict(const char *fname
)
5087 if (!(file
= fopen(fname
, "r"))) {
5088 log_module(NS_LOG
, LOG_ERROR
, "Unable to open dictionary file %s: %s", fname
, strerror(errno
));
5091 while (fgets(line
, sizeof(line
), file
)) {
5094 if (line
[strlen(line
)-1] == '\n')
5095 line
[strlen(line
)-1] = 0;
5096 dict_insert(nickserv_conf
.weak_password_dict
, strdup(line
), NULL
);
5099 log_module(NS_LOG
, LOG_INFO
, "Loaded %d words into weak password dictionary.", dict_size(nickserv_conf
.weak_password_dict
));
5102 static enum reclaim_action
5103 reclaim_action_from_string(const char *str
) {
5105 return RECLAIM_NONE
;
5106 else if (!irccasecmp(str
, "warn"))
5107 return RECLAIM_WARN
;
5108 else if (!irccasecmp(str
, "svsnick"))
5109 return RECLAIM_SVSNICK
;
5110 else if (!irccasecmp(str
, "kill"))
5111 return RECLAIM_KILL
;
5113 return RECLAIM_NONE
;
5117 nickserv_conf_read(void)
5119 dict_t conf_node
, child
;
5122 struct string_list
*strlist
;
5124 if (!(conf_node
= conf_get_data(NICKSERV_CONF_NAME
, RECDB_OBJECT
))) {
5125 log_module(NS_LOG
, LOG_ERROR
, "config node `%s' is missing or has wrong type.", NICKSERV_CONF_NAME
);
5128 str
= database_get_data(conf_node
, KEY_VALID_HANDLE_REGEX
, RECDB_QSTRING
);
5130 str
= database_get_data(conf_node
, KEY_VALID_ACCOUNT_REGEX
, RECDB_QSTRING
);
5131 if (nickserv_conf
.valid_handle_regex_set
)
5132 regfree(&nickserv_conf
.valid_handle_regex
);
5134 int err
= regcomp(&nickserv_conf
.valid_handle_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
5135 nickserv_conf
.valid_handle_regex_set
= !err
;
5136 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_account_regex (error %d)", err
);
5138 nickserv_conf
.valid_handle_regex_set
= 0;
5140 str
= database_get_data(conf_node
, KEY_VALID_NICK_REGEX
, RECDB_QSTRING
);
5141 if (nickserv_conf
.valid_nick_regex_set
)
5142 regfree(&nickserv_conf
.valid_nick_regex
);
5144 int err
= regcomp(&nickserv_conf
.valid_nick_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
5145 nickserv_conf
.valid_nick_regex_set
= !err
;
5146 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_nick_regex (error %d)", err
);
5148 nickserv_conf
.valid_nick_regex_set
= 0;
5150 str
= database_get_data(conf_node
, KEY_VALID_FAKEHOST_REGEX
, RECDB_QSTRING
);
5151 if (nickserv_conf
.valid_fakehost_regex_set
)
5152 regfree(&nickserv_conf
.valid_fakehost_regex
);
5154 int err
= regcomp(&nickserv_conf
.valid_fakehost_regex
, str
, REG_EXTENDED
|REG_ICASE
|REG_NOSUB
);
5155 nickserv_conf
.valid_fakehost_regex_set
= !err
;
5156 if (err
) log_module(NS_LOG
, LOG_ERROR
, "Bad valid_fakehost_regex (error %d)", err
);
5158 nickserv_conf
.valid_fakehost_regex_set
= 0;
5160 str
= database_get_data(conf_node
, KEY_NICKS_PER_HANDLE
, RECDB_QSTRING
);
5162 str
= database_get_data(conf_node
, KEY_NICKS_PER_ACCOUNT
, RECDB_QSTRING
);
5163 nickserv_conf
.nicks_per_handle
= str
? strtoul(str
, NULL
, 0) : 4;
5164 str
= database_get_data(conf_node
, KEY_DISABLE_NICKS
, RECDB_QSTRING
);
5165 nickserv_conf
.disable_nicks
= str
? strtoul(str
, NULL
, 0) : 0;
5166 str
= database_get_data(conf_node
, KEY_DEFAULT_HOSTMASK
, RECDB_QSTRING
);
5167 nickserv_conf
.default_hostmask
= str
? !disabled_string(str
) : 0;
5168 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_LENGTH
, RECDB_QSTRING
);
5169 nickserv_conf
.password_min_length
= str
? strtoul(str
, NULL
, 0) : 0;
5170 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_DIGITS
, RECDB_QSTRING
);
5171 nickserv_conf
.password_min_digits
= str
? strtoul(str
, NULL
, 0) : 0;
5172 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_UPPER
, RECDB_QSTRING
);
5173 nickserv_conf
.password_min_upper
= str
? strtoul(str
, NULL
, 0) : 0;
5174 str
= database_get_data(conf_node
, KEY_PASSWORD_MIN_LOWER
, RECDB_QSTRING
);
5175 nickserv_conf
.password_min_lower
= str
? strtoul(str
, NULL
, 0) : 0;
5176 str
= database_get_data(conf_node
, KEY_DB_BACKUP_FREQ
, RECDB_QSTRING
);
5177 nickserv_conf
.db_backup_frequency
= str
? ParseInterval(str
) : 7200;
5178 str
= database_get_data(conf_node
, KEY_MODOPER_LEVEL
, RECDB_QSTRING
);
5179 nickserv_conf
.modoper_level
= str
? strtoul(str
, NULL
, 0) : 900;
5180 str
= database_get_data(conf_node
, KEY_SET_EPITHET_LEVEL
, RECDB_QSTRING
);
5181 nickserv_conf
.set_epithet_level
= str
? strtoul(str
, NULL
, 0) : 1;
5182 str
= database_get_data(conf_node
, KEY_SET_TITLE_LEVEL
, RECDB_QSTRING
);
5183 nickserv_conf
.set_title_level
= str
? strtoul(str
, NULL
, 0) : 900;
5184 str
= database_get_data(conf_node
, KEY_SET_FAKEHOST_LEVEL
, RECDB_QSTRING
);
5185 nickserv_conf
.set_fakehost_level
= str
? strtoul(str
, NULL
, 0) : 1000;
5186 str
= database_get_data(conf_node
, KEY_HANDLE_EXPIRE_FREQ
, RECDB_QSTRING
);
5188 str
= database_get_data(conf_node
, KEY_ACCOUNT_EXPIRE_FREQ
, RECDB_QSTRING
);
5189 nickserv_conf
.handle_expire_frequency
= str
? ParseInterval(str
) : 86400;
5190 str
= database_get_data(conf_node
, KEY_HANDLE_EXPIRE_DELAY
, RECDB_QSTRING
);
5192 str
= database_get_data(conf_node
, KEY_ACCOUNT_EXPIRE_DELAY
, RECDB_QSTRING
);
5193 nickserv_conf
.handle_expire_delay
= str
? ParseInterval(str
) : 86400*30;
5194 str
= database_get_data(conf_node
, KEY_NOCHAN_HANDLE_EXPIRE_DELAY
, RECDB_QSTRING
);
5196 str
= database_get_data(conf_node
, KEY_NOCHAN_ACCOUNT_EXPIRE_DELAY
, RECDB_QSTRING
);
5197 nickserv_conf
.nochan_handle_expire_delay
= str
? ParseInterval(str
) : 86400*15;
5198 str
= database_get_data(conf_node
, "warn_clone_auth", RECDB_QSTRING
);
5199 nickserv_conf
.warn_clone_auth
= str
? !disabled_string(str
) : 1;
5200 str
= database_get_data(conf_node
, "default_maxlogins", RECDB_QSTRING
);
5201 nickserv_conf
.default_maxlogins
= str
? strtoul(str
, NULL
, 0) : 2;
5202 str
= database_get_data(conf_node
, "hard_maxlogins", RECDB_QSTRING
);
5203 nickserv_conf
.hard_maxlogins
= str
? strtoul(str
, NULL
, 0) : 10;
5204 str
= database_get_data(conf_node
, KEY_OUNREGISTER_INACTIVE
, RECDB_QSTRING
);
5205 nickserv_conf
.ounregister_inactive
= str
? ParseInterval(str
) : 86400*28;
5206 str
= database_get_data(conf_node
, KEY_OUNREGISTER_FLAGS
, RECDB_QSTRING
);
5209 nickserv_conf
.ounregister_flags
= 0;
5211 unsigned int pos
= handle_inverse_flags
[(unsigned char)*str
];
5214 nickserv_conf
.ounregister_flags
|= 1 << (pos
- 1);
5216 if (!nickserv_conf
.disable_nicks
) {
5217 str
= database_get_data(conf_node
, "reclaim_action", RECDB_QSTRING
);
5218 nickserv_conf
.reclaim_action
= str
? reclaim_action_from_string(str
) : RECLAIM_NONE
;
5219 str
= database_get_data(conf_node
, "warn_nick_owned", RECDB_QSTRING
);
5220 nickserv_conf
.warn_nick_owned
= str
? enabled_string(str
) : 0;
5221 str
= database_get_data(conf_node
, "auto_reclaim_action", RECDB_QSTRING
);
5222 nickserv_conf
.auto_reclaim_action
= str
? reclaim_action_from_string(str
) : RECLAIM_NONE
;
5223 str
= database_get_data(conf_node
, "auto_reclaim_delay", RECDB_QSTRING
);
5224 nickserv_conf
.auto_reclaim_delay
= str
? ParseInterval(str
) : 0;
5225 str
= database_get_data(conf_node
, KEY_NICK_EXPIRE_FREQ
, RECDB_QSTRING
);
5226 nickserv_conf
.nick_expire_frequency
= str
? ParseInterval(str
) : 86400;
5227 str
= database_get_data(conf_node
, KEY_NICK_EXPIRE_DELAY
, RECDB_QSTRING
);
5228 nickserv_conf
.nick_expire_delay
= str
? ParseInterval(str
) : 86400*30;
5229 str
= database_get_data(conf_node
, "expire_nicks", RECDB_QSTRING
);
5230 nickserv_conf
.expire_nicks
= str
? enabled_string(str
) : 0;
5232 child
= database_get_data(conf_node
, KEY_FLAG_LEVELS
, RECDB_OBJECT
);
5233 for (it
=dict_first(child
); it
; it
=iter_next(it
)) {
5234 const char *key
= iter_key(it
), *value
;
5238 if (!strncasecmp(key
, "uc_", 3))
5239 flag
= toupper(key
[3]);
5240 else if (!strncasecmp(key
, "lc_", 3))
5241 flag
= tolower(key
[3]);
5245 if ((pos
= handle_inverse_flags
[flag
])) {
5246 value
= GET_RECORD_QSTRING((struct record_data
*)iter_data(it
));
5247 flag_access_levels
[pos
- 1] = strtoul(value
, NULL
, 0);
5250 if (nickserv_conf
.weak_password_dict
)
5251 dict_delete(nickserv_conf
.weak_password_dict
);
5252 nickserv_conf
.weak_password_dict
= dict_new();
5253 dict_set_free_keys(nickserv_conf
.weak_password_dict
, free
);
5254 dict_insert(nickserv_conf
.weak_password_dict
, strdup("password"), NULL
);
5255 dict_insert(nickserv_conf
.weak_password_dict
, strdup("<password>"), NULL
);
5256 str
= database_get_data(conf_node
, KEY_DICT_FILE
, RECDB_QSTRING
);
5258 nickserv_load_dict(str
);
5259 str
= database_get_data(conf_node
, KEY_NICK
, RECDB_QSTRING
);
5260 if (nickserv
&& str
)
5261 NickChange(nickserv
, str
, 0);
5262 str
= database_get_data(conf_node
, KEY_AUTOGAG_ENABLED
, RECDB_QSTRING
);
5263 nickserv_conf
.autogag_enabled
= str
? strtoul(str
, NULL
, 0) : 1;
5264 str
= database_get_data(conf_node
, KEY_AUTOGAG_DURATION
, RECDB_QSTRING
);
5265 nickserv_conf
.autogag_duration
= str
? ParseInterval(str
) : 1800;
5266 str
= database_get_data(conf_node
, KEY_EMAIL_VISIBLE_LEVEL
, RECDB_QSTRING
);
5267 nickserv_conf
.email_visible_level
= str
? strtoul(str
, NULL
, 0) : 800;
5268 str
= database_get_data(conf_node
, KEY_EMAIL_ENABLED
, RECDB_QSTRING
);
5269 nickserv_conf
.email_enabled
= str
? enabled_string(str
) : 0;
5270 str
= database_get_data(conf_node
, KEY_SYNC_LOG
, RECDB_QSTRING
);
5271 nickserv_conf
.sync_log
= str
? enabled_string(str
) : 0;
5272 str
= database_get_data(conf_node
, KEY_COOKIE_TIMEOUT
, RECDB_QSTRING
);
5273 nickserv_conf
.cookie_timeout
= str
? ParseInterval(str
) : 24*3600;
5274 str
= database_get_data(conf_node
, KEY_EMAIL_REQUIRED
, RECDB_QSTRING
);
5275 nickserv_conf
.email_required
= (nickserv_conf
.email_enabled
&& str
) ? enabled_string(str
) : 0;
5276 str
= database_get_data(conf_node
, KEY_ACCOUNTS_PER_EMAIL
, RECDB_QSTRING
);
5277 nickserv_conf
.handles_per_email
= str
? strtoul(str
, NULL
, 0) : 1;
5278 str
= database_get_data(conf_node
, KEY_EMAIL_SEARCH_LEVEL
, RECDB_QSTRING
);
5279 nickserv_conf
.email_search_level
= str
? strtoul(str
, NULL
, 0) : 600;
5280 str
= database_get_data(conf_node
, KEY_TITLEHOST_SUFFIX
, RECDB_QSTRING
);
5281 nickserv_conf
.titlehost_suffix
= str
? str
: "example.net";
5283 free_string_list(nickserv_conf
.denied_fakehost_words
);
5284 strlist
= database_get_data(conf_node
, KEY_DENIED_FAKEHOST_WORDS
, RECDB_STRING_LIST
);
5286 strlist
= string_list_copy(strlist
);
5288 strlist
= alloc_string_list(4);
5289 string_list_append(strlist
, strdup("sex"));
5290 string_list_append(strlist
, strdup("fuck"));
5292 nickserv_conf
.denied_fakehost_words
= strlist
;
5294 str
= database_get_data(conf_node
, KEY_DEFAULT_STYLE
, RECDB_QSTRING
);
5295 nickserv_conf
.default_style
= str
? str
[0] : HI_DEFAULT_STYLE
;
5297 str
= database_get_data(conf_node
, KEY_AUTO_OPER
, RECDB_QSTRING
);
5298 nickserv_conf
.auto_oper
= str
? str
: "";
5300 str
= database_get_data(conf_node
, KEY_AUTO_ADMIN
, RECDB_QSTRING
);
5301 nickserv_conf
.auto_admin
= str
? str
: "";
5303 str
= database_get_data(conf_node
, KEY_AUTO_OPER_PRIVS
, RECDB_QSTRING
);
5304 nickserv_conf
.auto_oper_privs
= str
? str
: "";
5306 str
= database_get_data(conf_node
, KEY_AUTO_ADMIN_PRIVS
, RECDB_QSTRING
);
5307 nickserv_conf
.auto_admin_privs
= str
? str
: "";
5309 str
= conf_get_data("server/network", RECDB_QSTRING
);
5310 nickserv_conf
.network_name
= str
? str
: "some IRC network";
5311 if (!nickserv_conf
.auth_policer_params
) {
5312 nickserv_conf
.auth_policer_params
= policer_params_new();
5313 policer_params_set(nickserv_conf
.auth_policer_params
, "size", "5");
5314 policer_params_set(nickserv_conf
.auth_policer_params
, "drain-rate", "0.05");
5316 child
= database_get_data(conf_node
, KEY_AUTH_POLICER
, RECDB_OBJECT
);
5317 for (it
=dict_first(child
); it
; it
=iter_next(it
))
5318 set_policer_param(iter_key(it
), iter_data(it
), nickserv_conf
.auth_policer_params
);
5320 str
= database_get_data(conf_node
, KEY_LDAP_ENABLE
, RECDB_QSTRING
);
5321 nickserv_conf
.ldap_enable
= str
? strtoul(str
, NULL
, 0) : 0;
5323 str
= database_get_data(conf_node
, KEY_FORCE_HANDLES_LOWERCASE
, RECDB_QSTRING
);
5324 nickserv_conf
.force_handles_lowercase
= str
? strtol(str
, NULL
, 0) : 0;
5327 if(nickserv_conf
.ldap_enable
> 0) {
5328 /* ldap is enabled but not compiled in - error out */
5329 log_module(MAIN_LOG
, LOG_ERROR
, "ldap is enabled in config, but not compiled in!");
5330 nickserv_conf
.ldap_enable
= 0;
5336 str
= database_get_data(conf_node
, KEY_LDAP_URI
, RECDB_QSTRING
);
5337 nickserv_conf
.ldap_uri
= str
? str
: "";
5339 str
= database_get_data(conf_node
, KEY_LDAP_BASE
, RECDB_QSTRING
);
5340 nickserv_conf
.ldap_base
= str
? str
: "";
5342 str
= database_get_data(conf_node
, KEY_LDAP_DN_FMT
, RECDB_QSTRING
);
5343 nickserv_conf
.ldap_dn_fmt
= str
? str
: "";
5345 str
= database_get_data(conf_node
, KEY_LDAP_VERSION
, RECDB_QSTRING
);
5346 nickserv_conf
.ldap_version
= str
? strtoul(str
, NULL
, 0) : 3;
5348 str
= database_get_data(conf_node
, KEY_LDAP_AUTOCREATE
, RECDB_QSTRING
);
5349 nickserv_conf
.ldap_autocreate
= str
? strtoul(str
, NULL
, 0) : 0;
5351 str
= database_get_data(conf_node
, KEY_LDAP_TIMEOUT
, RECDB_QSTRING
);
5352 nickserv_conf
.ldap_timeout
= str
? strtoul(str
, NULL
, 0) : 5;
5354 str
= database_get_data(conf_node
, KEY_LDAP_ADMIN_DN
, RECDB_QSTRING
);
5355 nickserv_conf
.ldap_admin_dn
= str
? str
: "";
5357 str
= database_get_data(conf_node
, KEY_LDAP_ADMIN_PASS
, RECDB_QSTRING
);
5358 nickserv_conf
.ldap_admin_pass
= str
? str
: "";
5360 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_ACCOUNT
, RECDB_QSTRING
);
5361 nickserv_conf
.ldap_field_account
= str
? str
: "";
5363 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_PASSWORD
, RECDB_QSTRING
);
5364 nickserv_conf
.ldap_field_password
= str
? str
: "";
5366 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_EMAIL
, RECDB_QSTRING
);
5367 nickserv_conf
.ldap_field_email
= str
? str
: "";
5369 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_OSLEVEL
, RECDB_QSTRING
);
5370 nickserv_conf
.ldap_field_oslevel
= str
? str
: "";
5372 str
= database_get_data(conf_node
, KEY_LDAP_OPER_GROUP_DN
, RECDB_QSTRING
);
5373 nickserv_conf
.ldap_oper_group_dn
= str
? str
: "";
5375 str
= database_get_data(conf_node
, KEY_LDAP_OPER_GROUP_LEVEL
, RECDB_QSTRING
);
5376 nickserv_conf
.ldap_oper_group_level
= str
? strtoul(str
, NULL
, 0) : 99;
5378 str
= database_get_data(conf_node
, KEY_LDAP_FIELD_GROUP_MEMBER
, RECDB_QSTRING
);
5379 nickserv_conf
.ldap_field_group_member
= str
? str
: "";
5381 free_string_list(nickserv_conf
.ldap_object_classes
);
5382 strlist
= database_get_data(conf_node
, KEY_LDAP_OBJECT_CLASSES
, RECDB_STRING_LIST
);
5384 strlist
= string_list_copy(strlist
);
5386 strlist
= alloc_string_list(4);
5387 string_list_append(strlist
, strdup("top"));
5389 nickserv_conf
.ldap_object_classes
= strlist
;
5396 nickserv_reclaim(struct userNode
*user
, struct nick_info
*ni
, enum reclaim_action action
) {
5398 char newnick
[NICKLEN
+1];
5411 send_message(user
, nickserv
, "NSMSG_RECLAIM_WARN", ni
->nick
, ni
->owner
->handle
);
5412 send_message(user
, nickserv
, "NSMSG_RECLAIM_HOWTO", ni
->owner
->handle
, nickserv
->nick
, self
->name
, ni
->owner
->handle
);
5414 case RECLAIM_SVSNICK
:
5416 snprintf(newnick
, sizeof(newnick
), "Guest%d", rand()%10000
);
5417 } while (GetUserH(newnick
));
5418 irc_svsnick(nickserv
, user
, newnick
);
5421 msg
= user_find_message(user
, "NSMSG_RECLAIM_KILL");
5422 DelUser(user
, nickserv
, 1, msg
);
5428 nickserv_reclaim_p(void *data
) {
5429 struct userNode
*user
= data
;
5430 struct nick_info
*ni
= get_nick_info(user
->nick
);
5432 nickserv_reclaim(user
, ni
, nickserv_conf
.auto_reclaim_action
);
5436 check_user_nick(struct userNode
*user
, UNUSED_ARG(void *extra
)) {
5437 struct nick_info
*ni
;
5438 user
->modes
&= ~FLAGS_REGNICK
;
5440 if (!(ni
= get_nick_info(user
->nick
)))
5442 if (user
->handle_info
== ni
->owner
) {
5443 user
->modes
|= FLAGS_REGNICK
;
5447 if (nickserv_conf
.warn_nick_owned
)
5448 send_message(user
, nickserv
, "NSMSG_RECLAIM_WARN", ni
->nick
, ni
->owner
->handle
);
5449 send_message(user
, nickserv
, "NSMSG_RECLAIM_HOWTO", ni
->owner
->handle
, nickserv
->nick
, self
->name
, ni
->owner
->handle
);
5450 if (nickserv_conf
.auto_reclaim_action
== RECLAIM_NONE
)
5452 if (nickserv_conf
.auto_reclaim_delay
)
5453 timeq_add(now
+ nickserv_conf
.auto_reclaim_delay
, nickserv_reclaim_p
, user
);
5455 nickserv_reclaim(user
, ni
, nickserv_conf
.auto_reclaim_action
);
5461 new_user_event(struct userNode
*user
, void *extra
) {
5462 /* If the user's server is not bursting,
5463 * the user is authed, the account has autohide set
5464 * and the user doesn't have user mode +x then apply
5465 * the autohide setting.
5467 if (!user
->uplink
->burst
&& user
->handle_info
&&
5468 HANDLE_FLAGGED(user
->handle_info
, AUTOHIDE
) &&
5469 !IsHiddenHost(user
))
5470 irc_umode(user
, "+x");
5472 return check_user_nick(user
, extra
);
5476 handle_account(struct userNode
*user
, const char *stamp
)
5478 struct handle_info
*hi
;
5481 #ifdef WITH_PROTOCOL_P10
5482 time_t timestamp
= 0;
5484 colon
= strchr(stamp
, ':');
5485 if(colon
&& colon
[1])
5488 timestamp
= atoi(colon
+1);
5490 hi
= dict_find(nickserv_handle_dict
, stamp
, NULL
);
5491 if(hi
&& timestamp
&& hi
->registered
!= timestamp
)
5493 log_module(MAIN_LOG
, LOG_WARNING
, "%s using account %s but timestamp does not match %s is not %s.", user
->nick
, stamp
, ctime(×tamp
),
5494 ctime(&hi
->registered
));
5498 hi
= dict_find(nickserv_id_dict
, stamp
, NULL
);
5499 log_module(MAIN_LOG
, LOG_WARNING
, "Using non-P10 code in accounts, not tested at all!");
5503 if(!hi
&& nickserv_conf
.ldap_enable
&& nickserv_conf
.ldap_autocreate
&&
5504 (ldap_user_exists(stamp
) == LDAP_SUCCESS
)) {
5510 /* First attempt to get the email address from LDAP */
5511 if((rc
= ldap_get_user_info(stamp
, &email
) != LDAP_SUCCESS
))
5512 if(nickserv_conf
.email_required
)
5515 /* Now try to register the handle */
5516 if (cont
&& (hi
= nickserv_register(user
, user
, stamp
, NULL
, 1))) {
5517 if(nickserv_conf
.default_hostmask
)
5520 mask
= generate_hostmask(user
, GENMASK_OMITNICK
|GENMASK_NO_HIDING
|GENMASK_ANY_IDENT
);
5523 char* mask_canonicalized
= canonicalize_hostmask(strdup(mask
));
5524 string_list_append(hi
->masks
, mask_canonicalized
);
5528 nickserv_set_email_addr(hi
, email
);
5536 if (HANDLE_FLAGGED(hi
, SUSPENDED
)) {
5539 set_user_handle_info(user
, hi
, 0);
5541 log_module(MAIN_LOG
, LOG_WARNING
, "%s had unknown account stamp %s.", user
->nick
, stamp
);
5546 handle_nick_change(struct userNode
*user
, const char *old_nick
, UNUSED_ARG(void *extra
))
5548 struct handle_info
*hi
;
5550 if ((hi
= dict_find(nickserv_allow_auth_dict
, old_nick
, 0))) {
5551 dict_remove(nickserv_allow_auth_dict
, old_nick
);
5552 dict_insert(nickserv_allow_auth_dict
, user
->nick
, hi
);
5554 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
5555 check_user_nick(user
, NULL
);
5559 nickserv_remove_user(struct userNode
*user
, UNUSED_ARG(struct userNode
*killer
), UNUSED_ARG(const char *why
), UNUSED_ARG(void *extra
))
5561 dict_remove(nickserv_allow_auth_dict
, user
->nick
);
5562 timeq_del(0, nickserv_reclaim_p
, user
, TIMEQ_IGNORE_WHEN
);
5563 set_user_handle_info(user
, NULL
, 0);
5566 static struct modcmd
*
5567 nickserv_define_func(const char *name
, modcmd_func_t func
, int min_level
, int must_auth
, int must_be_qualified
)
5569 if (min_level
> 0) {
5571 sprintf(buf
, "%u", min_level
);
5572 if (must_be_qualified
) {
5573 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "level", buf
, "flags", "+qualified,+loghostmask", NULL
);
5575 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "level", buf
, NULL
);
5577 } else if (min_level
== 0) {
5578 if (must_be_qualified
) {
5579 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+helping", NULL
);
5581 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+helping", NULL
);
5584 if (must_be_qualified
) {
5585 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), "flags", "+qualified,+loghostmask", NULL
);
5587 return modcmd_register(nickserv_module
, name
, func
, 1, (must_auth
? MODCMD_REQUIRE_AUTHED
: 0), NULL
);
5592 #define SDFLAG_STALE 0x01 /**< SASL session data is stale, delete on next pass. */
5596 struct SASLSession
*next
;
5597 struct SASLSession
*prev
;
5598 struct server
* source
;
5608 struct SASLSession
*saslsessions
= NULL
;
5611 sasl_delete_session(struct SASLSession
*session
)
5618 session
->buf
= NULL
;
5620 if (session
->sslclifp
)
5621 free(session
->sslclifp
);
5622 session
->sslclifp
= NULL
;
5624 if (session
->hostmask
)
5625 free(session
->hostmask
);
5626 session
->hostmask
= NULL
;
5629 session
->next
->prev
= session
->prev
;
5631 session
->prev
->next
= session
->next
;
5633 saslsessions
= session
->next
;
5639 sasl_delete_stale(UNUSED_ARG(void *data
))
5643 struct SASLSession
*sess
= NULL
;
5644 struct SASLSession
*nextsess
= NULL
;
5646 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Checking for stale sessions");
5648 for (sess
= saslsessions
; sess
; sess
= nextsess
)
5650 nextsess
= sess
->next
;
5652 if (sess
->flags
& SDFLAG_STALE
)
5655 sasl_delete_session(sess
);
5660 sess
->flags
|= SDFLAG_STALE
;
5665 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Deleted %d stale sessions, %d remaining", delcount
, remcount
);
5667 timeq_add(now
+ 30, sasl_delete_stale
, NULL
);
5671 sasl_get_session(const char *uid
)
5673 struct SASLSession
*sess
;
5675 for (sess
= saslsessions
; sess
; sess
= sess
->next
)
5677 if (!strncmp(sess
->uid
, uid
, 128))
5679 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Found session for %s", sess
->uid
);
5684 sess
= malloc(sizeof(struct SASLSession
));
5685 memset(sess
, 0, sizeof(struct SASLSession
));
5687 strncpy(sess
->uid
, uid
, 128);
5690 timeq_add(now
+ 30, sasl_delete_stale
, NULL
);
5693 saslsessions
->prev
= sess
;
5694 sess
->next
= saslsessions
;
5695 saslsessions
= sess
;
5697 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Created session for %s", sess
->uid
);
5702 sasl_packet(struct SASLSession
*session
)
5704 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Got packet containing: %s", session
->buf
);
5706 if (!session
->mech
[0])
5708 log_module(NS_LOG
, LOG_DEBUG
, "SASL: No mechanism stored yet, using %s", session
->buf
);
5709 if (strcmp(session
->buf
, "PLAIN") && (strcmp(session
->buf
, "EXTERNAL") || !session
->sslclifp
)) {
5710 if (!session
->sslclifp
)
5711 irc_sasl(session
->source
, session
->uid
, "M", "PLAIN");
5713 irc_sasl(session
->source
, session
->uid
, "M", "PLAIN,EXTERNAL");
5714 irc_sasl(session
->source
, session
->uid
, "D", "F");
5715 sasl_delete_session(session
);
5719 strncpy(session
->mech
, session
->buf
, 10);
5720 irc_sasl(session
->source
, session
->uid
, "C", "+");
5722 else if (!strcmp(session
->mech
, "EXTERNAL"))
5726 char *authzid
= NULL
;
5727 struct handle_info
*hi
= NULL
;
5728 static char buffer
[256];
5730 base64_decode_alloc(session
->buf
, session
->buflen
, &raw
, &rawlen
);
5735 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Checking supplied credentials");
5737 if (!session
->sslclifp
) {
5738 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Incomplete credentials supplied");
5739 irc_sasl(session
->source
, session
->uid
, "D", "F");
5741 if (!(hi
= loc_auth(session
->sslclifp
, authzid
, NULL
, session
->hostmask
)))
5743 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Invalid credentials supplied");
5744 irc_sasl(session
->source
, session
->uid
, "D", "F");
5748 snprintf(buffer
, sizeof(buffer
), "%s "FMT_TIME_T
, hi
->handle
, hi
->registered
);
5749 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Valid credentials supplied");
5750 irc_sasl(session
->source
, session
->uid
, "L", buffer
);
5751 irc_sasl(session
->source
, session
->uid
, "D", "S");
5755 sasl_delete_session(session
);
5764 char *authzid
= NULL
;
5765 char *authcid
= NULL
;
5766 char *passwd
= NULL
;
5768 unsigned int i
= 0, c
= 0;
5769 struct handle_info
*hi
= NULL
;
5770 struct handle_info
*hii
= NULL
;
5771 static char buffer
[256];
5773 base64_decode_alloc(session
->buf
, session
->buflen
, &raw
, &rawlen
);
5775 raw
= (char *)realloc(raw
, rawlen
+1);
5780 for (i
=0; i
<rawlen
; i
++)
5791 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Checking supplied credentials");
5793 if ((c
!= 2) || !(*authcid
))
5795 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Incomplete credentials supplied");
5796 irc_sasl(session
->source
, session
->uid
, "D", "F");
5800 if (!(hi
= loc_auth(session
->sslclifp
, authcid
, passwd
, session
->hostmask
)))
5802 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Invalid credentials supplied");
5803 irc_sasl(session
->source
, session
->uid
, "D", "F");
5807 if (*authzid
&& irccasecmp(authzid
, authcid
))
5809 if (HANDLE_FLAGGED(hi
, IMPERSONATE
))
5812 hi
= get_handle_info(authzid
);
5816 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Impersonation unauthorized");
5824 log_module(NS_LOG
, LOG_DEBUG
, "SASL: %s is ipersonating %s", hii
->handle
, hi
->handle
);
5825 snprintf(buffer
, sizeof(buffer
), "%s "FMT_TIME_T
, hii
->handle
, hii
->registered
);
5826 irc_sasl(session
->source
, session
->uid
, "I", buffer
);
5828 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Valid credentials supplied");
5829 snprintf(buffer
, sizeof(buffer
), "%s "FMT_TIME_T
, hi
->handle
, hi
->registered
);
5830 irc_sasl(session
->source
, session
->uid
, "L", buffer
);
5831 irc_sasl(session
->source
, session
->uid
, "D", "S");
5835 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Invalid credentials supplied");
5836 irc_sasl(session
->source
, session
->uid
, "D", "F");
5841 sasl_delete_session(session
);
5847 /* clear stale state */
5848 session
->flags
&= ~SDFLAG_STALE
;
5852 handle_sasl_input(struct server
* source
,const char *uid
, const char *subcmd
, const char *data
, const char *ext
, UNUSED_ARG(void *extra
))
5854 struct SASLSession
* sess
= sasl_get_session(uid
);
5855 int len
= strlen(data
);
5857 sess
->source
= source
;
5859 if (!strcmp(subcmd
, "D"))
5861 sasl_delete_session(sess
);
5865 if (!strcmp(subcmd
, "H")) {
5866 log_module(NS_LOG
, LOG_DEBUG
, "SASL: Storing host mask %s", data
);
5867 sess
->hostmask
= strdup(data
);
5871 if (strcmp(subcmd
, "S") && strcmp(subcmd
, "C"))
5877 if (sess
->p
== NULL
)
5879 sess
->buf
= (char *)malloc(len
+ 1);
5880 sess
->p
= sess
->buf
;
5885 if (sess
->buflen
+ len
+ 1 > 8192) /* This is a little much... */
5887 irc_sasl(source
, uid
, "D", "F");
5888 sasl_delete_session(sess
);
5892 sess
->buf
= (char *)realloc(sess
->buf
, sess
->buflen
+ len
+ 1);
5893 sess
->p
= sess
->buf
+ sess
->buflen
;
5894 sess
->buflen
+= len
;
5897 memcpy(sess
->p
, data
, len
);
5898 sess
->buf
[len
] = '\0';
5901 sess
->sslclifp
= strdup(ext
);
5903 /* Messages not exactly 400 bytes are the end of a packet. */
5908 if (sess
->buf
!= NULL
)
5910 sess
->buf
= sess
->p
= NULL
;
5915 nickserv_db_cleanup(UNUSED_ARG(void* extra
))
5917 unreg_del_user_func(nickserv_remove_user
, NULL
);
5918 unreg_sasl_input_func(handle_sasl_input
, NULL
);
5919 userList_clean(&curr_helpers
);
5920 policer_params_delete(nickserv_conf
.auth_policer_params
);
5921 dict_delete(nickserv_handle_dict
);
5922 dict_delete(nickserv_nick_dict
);
5923 dict_delete(nickserv_opt_dict
);
5924 dict_delete(nickserv_allow_auth_dict
);
5925 dict_delete(nickserv_email_dict
);
5926 dict_delete(nickserv_id_dict
);
5927 dict_delete(nickserv_conf
.weak_password_dict
);
5928 free(auth_func_list
);
5929 free(auth_func_list_extra
);
5930 free(unreg_func_list
);
5931 free(unreg_func_list_extra
);
5933 free(rf_list_extra
);
5934 free(allowauth_func_list
);
5935 free(allowauth_func_list_extra
);
5936 free(handle_merge_func_list
);
5937 free(handle_merge_func_list_extra
);
5938 free(failpw_func_list
);
5939 free(failpw_func_list_extra
);
5940 if (nickserv_conf
.valid_handle_regex_set
)
5941 regfree(&nickserv_conf
.valid_handle_regex
);
5942 if (nickserv_conf
.valid_nick_regex_set
)
5943 regfree(&nickserv_conf
.valid_nick_regex
);
5946 void handle_loc_auth_oper(struct userNode
*user
, UNUSED_ARG(struct handle_info
*old_handle
), UNUSED_ARG(void *extra
)) {
5947 char *privv
[MAXNUMPARAMS
];
5950 if (!*nickserv_conf
.auto_oper
|| !user
->handle_info
)
5953 if (!IsOper(user
)) {
5954 if (*nickserv_conf
.auto_admin
&& user
->handle_info
->opserv_level
>= opserv_conf_admin_level()) {
5955 if (nickserv_conf
.auto_admin_privs
[0]) {
5956 irc_raw_privs(user
, nickserv_conf
.auto_admin_privs
);
5957 privc
= split_line(strdup(nickserv_conf
.auto_admin_privs
), false, MAXNUMPARAMS
, privv
);
5958 for (i
= 0; i
< privc
; i
++) {
5959 client_modify_priv_by_name(user
, privv
[i
], 1);
5962 irc_umode(user
, nickserv_conf
.auto_admin
);
5963 irc_sno(0x1, "%s (%s@%s) is now an IRC Administrator",
5964 user
->nick
, user
->ident
, user
->hostname
);
5965 send_message(user
, nickserv
, "NSMSG_AUTO_OPER_ADMIN");
5966 } else if (*nickserv_conf
.auto_oper
&& user
->handle_info
->opserv_level
) {
5967 if (nickserv_conf
.auto_oper_privs
[0]) {
5968 irc_raw_privs(user
, nickserv_conf
.auto_oper_privs
);
5969 privc
= split_line(strdup(nickserv_conf
.auto_oper_privs
), false, MAXNUMPARAMS
, privv
);
5970 for (i
= 0; i
< privc
; i
++) {
5971 client_modify_priv_by_name(user
, privv
[i
], 1);
5974 irc_umode(user
, nickserv_conf
.auto_oper
);
5975 irc_sno(0x1, "%s (%s@%s) is now an IRC Operator",
5976 user
->nick
, user
->ident
, user
->hostname
);
5977 send_message(user
, nickserv
, "NSMSG_AUTO_OPER");
5983 init_nickserv(const char *nick
)
5985 struct chanNode
*chan
;
5987 NS_LOG
= log_register_type("NickServ", "file:nickserv.log");
5988 reg_new_user_func(new_user_event
, NULL
);
5989 reg_nick_change_func(handle_nick_change
, NULL
);
5990 reg_del_user_func(nickserv_remove_user
, NULL
);
5991 reg_account_func(handle_account
);
5992 reg_auth_func(handle_loc_auth_oper
, NULL
);
5993 reg_sasl_input_func(handle_sasl_input
, NULL
);
5995 /* set up handle_inverse_flags */
5996 memset(handle_inverse_flags
, 0, sizeof(handle_inverse_flags
));
5997 for (i
=0; handle_flags
[i
]; i
++) {
5998 handle_inverse_flags
[(unsigned char)handle_flags
[i
]] = i
+ 1;
5999 flag_access_levels
[i
] = 0;
6000 /* ensure flag I requires a minimum of 999 if not set in the config */
6001 if ((unsigned char)handle_flags
[i
] == 'I')
6002 flag_access_levels
[i
] = 999;
6005 conf_register_reload(nickserv_conf_read
);
6006 nickserv_opt_dict
= dict_new();
6007 nickserv_email_dict
= dict_new();
6009 dict_set_free_keys(nickserv_email_dict
, free
);
6010 dict_set_free_data(nickserv_email_dict
, nickserv_free_email_addr
);
6012 nickserv_module
= module_register("NickServ", NS_LOG
, "nickserv.help", NULL
);
6013 /* Removed qualified_host as default requirement for AUTH, REGISTER, PASS, etc. nets
6014 * can enable it per command using modcmd. (its a shitty default IMO, and now in 1.3
6015 * a big pain to disable since its nolonger in the config file. ) -Rubin
6017 modcmd_register(nickserv_module
, "AUTH", cmd_auth
, 2, MODCMD_KEEP_BOUND
, "flags", "+loghostmask", NULL
);
6018 nickserv_define_func("ALLOWAUTH", cmd_allowauth
, 0, 1, 0);
6019 nickserv_define_func("REGISTER", cmd_register
, -1, 0, 0);
6020 nickserv_define_func("OREGISTER", cmd_oregister
, 0, 1, 0);
6021 nickserv_define_func("UNREGISTER", cmd_unregister
, -1, 1, 0);
6022 nickserv_define_func("OUNREGISTER", cmd_ounregister
, 0, 1, 0);
6023 nickserv_define_func("ADDMASK", cmd_addmask
, -1, 1, 0);
6024 nickserv_define_func("OADDMASK", cmd_oaddmask
, 0, 1, 0);
6025 nickserv_define_func("DELMASK", cmd_delmask
, -1, 1, 0);
6026 nickserv_define_func("ODELMASK", cmd_odelmask
, 0, 1, 0);
6027 nickserv_define_func("ADDSSLFP", cmd_addsslfp
, -1, 1, 0);
6028 nickserv_define_func("OADDSSLFP", cmd_oaddsslfp
, 0, 1, 0);
6029 nickserv_define_func("DELSSLFP", cmd_delsslfp
, -1, 1, 0);
6030 nickserv_define_func("ODELSSLFP", cmd_odelsslfp
, 0, 1, 0);
6031 nickserv_define_func("PASS", cmd_pass
, -1, 1, 0);
6032 nickserv_define_func("SET", cmd_set
, -1, 1, 0);
6033 nickserv_define_func("OSET", cmd_oset
, 0, 1, 0);
6034 nickserv_define_func("ACCOUNTINFO", cmd_handleinfo
, -1, 0, 0);
6035 nickserv_define_func("USERINFO", cmd_userinfo
, -1, 1, 0);
6036 nickserv_define_func("RENAME", cmd_rename_handle
, -1, 1, 0);
6037 nickserv_define_func("VACATION", cmd_vacation
, -1, 1, 0);
6038 nickserv_define_func("MERGE", cmd_merge
, 750, 1, 0);
6039 if (!nickserv_conf
.disable_nicks
) {
6040 /* nick management commands */
6041 nickserv_define_func("REGNICK", cmd_regnick
, -1, 1, 0);
6042 nickserv_define_func("OREGNICK", cmd_oregnick
, 0, 1, 0);
6043 nickserv_define_func("UNREGNICK", cmd_unregnick
, -1, 1, 0);
6044 nickserv_define_func("OUNREGNICK", cmd_ounregnick
, 0, 1, 0);
6045 nickserv_define_func("NICKINFO", cmd_nickinfo
, -1, 1, 0);
6046 nickserv_define_func("RECLAIM", cmd_reclaim
, -1, 1, 0);
6048 if (nickserv_conf
.email_enabled
) {
6049 nickserv_define_func("AUTHCOOKIE", cmd_authcookie
, -1, 0, 0);
6050 nickserv_define_func("RESETPASS", cmd_resetpass
, -1, 0, 0);
6051 nickserv_define_func("COOKIE", cmd_cookie
, -1, 0, 0);
6052 nickserv_define_func("DELCOOKIE", cmd_delcookie
, -1, 1, 0);
6053 nickserv_define_func("ODELCOOKIE", cmd_odelcookie
, 0, 1, 0);
6054 dict_insert(nickserv_opt_dict
, "EMAIL", opt_email
);
6056 nickserv_define_func("GHOST", cmd_ghost
, -1, 1, 0);
6057 /* ignore commands */
6058 nickserv_define_func("ADDIGNORE", cmd_addignore
, -1, 1, 0);
6059 nickserv_define_func("OADDIGNORE", cmd_oaddignore
, 0, 1, 0);
6060 nickserv_define_func("DELIGNORE", cmd_delignore
, -1, 1, 0);
6061 nickserv_define_func("ODELIGNORE", cmd_odelignore
, 0, 1, 0);
6062 /* miscellaneous commands */
6063 nickserv_define_func("STATUS", cmd_status
, -1, 0, 0);
6064 nickserv_define_func("SEARCH", cmd_search
, 100, 1, 0);
6065 nickserv_define_func("SEARCH UNREGISTER", NULL
, 800, 1, 0);
6066 nickserv_define_func("MERGEDB", cmd_mergedb
, 999, 1, 0);
6067 nickserv_define_func("CHECKPASS", cmd_checkpass
, 601, 1, 0);
6068 nickserv_define_func("CHECKEMAIL", cmd_checkemail
, 0, 1, 0);
6070 dict_insert(nickserv_opt_dict
, "INFO", opt_info
);
6071 dict_insert(nickserv_opt_dict
, "WIDTH", opt_width
);
6072 dict_insert(nickserv_opt_dict
, "TABLEWIDTH", opt_tablewidth
);
6073 dict_insert(nickserv_opt_dict
, "COLOR", opt_color
);
6074 dict_insert(nickserv_opt_dict
, "PRIVMSG", opt_privmsg
);
6075 dict_insert(nickserv_opt_dict
, "AUTOHIDE", opt_autohide
);
6076 dict_insert(nickserv_opt_dict
, "STYLE", opt_style
);
6077 dict_insert(nickserv_opt_dict
, "PASS", opt_password
);
6078 dict_insert(nickserv_opt_dict
, "PASSWORD", opt_password
);
6079 dict_insert(nickserv_opt_dict
, "FLAGS", opt_flags
);
6080 dict_insert(nickserv_opt_dict
, "ACCESS", opt_level
);
6081 dict_insert(nickserv_opt_dict
, "LEVEL", opt_level
);
6082 dict_insert(nickserv_opt_dict
, "EPITHET", opt_epithet
);
6083 dict_insert(nickserv_opt_dict
, "NOTE", opt_note
);
6084 if (nickserv_conf
.titlehost_suffix
) {
6085 dict_insert(nickserv_opt_dict
, "TITLE", opt_title
);
6086 dict_insert(nickserv_opt_dict
, "FAKEHOST", opt_fakehost
);
6088 dict_insert(nickserv_opt_dict
, "ANNOUNCEMENTS", opt_announcements
);
6089 dict_insert(nickserv_opt_dict
, "MAXLOGINS", opt_maxlogins
);
6090 dict_insert(nickserv_opt_dict
, "ADVANCED", opt_advanced
);
6091 dict_insert(nickserv_opt_dict
, "LANGUAGE", opt_language
);
6092 dict_insert(nickserv_opt_dict
, "KARMA", opt_karma
);
6094 nickserv_handle_dict
= dict_new();
6095 dict_set_free_keys(nickserv_handle_dict
, free
);
6096 dict_set_free_data(nickserv_handle_dict
, free_handle_info
);
6098 nickserv_id_dict
= dict_new();
6099 dict_set_free_keys(nickserv_id_dict
, free
);
6101 nickserv_nick_dict
= dict_new();
6102 dict_set_free_data(nickserv_nick_dict
, free
);
6104 nickserv_allow_auth_dict
= dict_new();
6106 userList_init(&curr_helpers
);
6109 const char *modes
= conf_get_data("services/nickserv/modes", RECDB_QSTRING
);
6110 nickserv
= AddLocalUser(nick
, nick
, NULL
, "Nick Services", modes
);
6111 nickserv_service
= service_register(nickserv
);
6113 saxdb_register("NickServ", nickserv_saxdb_read
, nickserv_saxdb_write
);
6114 reg_exit_func(nickserv_db_cleanup
, NULL
);
6115 if(nickserv_conf
.handle_expire_frequency
)
6116 timeq_add(now
+ nickserv_conf
.handle_expire_frequency
, expire_handles
, NULL
);
6117 if(nickserv_conf
.nick_expire_frequency
&& nickserv_conf
.expire_nicks
)
6118 timeq_add(now
+ nickserv_conf
.nick_expire_frequency
, expire_nicks
, NULL
);
6120 if(autojoin_channels
&& nickserv
) {
6121 for (i
= 0; i
< autojoin_channels
->used
; i
++) {
6122 chan
= AddChannel(autojoin_channels
->list
[i
], now
, "+nt", NULL
, NULL
);
6123 AddChannelUser(nickserv
, chan
)->modes
|= MODE_CHANOP
;
6128 ldap_do_init(nickserv_conf
);
6131 message_register_table(msgtab
);