ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/src/account/myuser.C
Revision: 1.2
Committed: Sat Jul 21 01:29:13 2007 UTC (19 years, 2 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.1: +6 -9 lines
Log Message:
- moved to new documentation system
- fixed small build error

File Contents

# User Rev Content
1 pippijn 1.1 #include "atheme.h"
2     #include <account/myuser.h>
3     #include <account/mynick.h>
4     #include <account/chanacs.h>
5     #include <account/mychan.h>
6     #include <account/mymemo.h>
7 pippijn 1.2 #include <common/util.h>
8 pippijn 1.1 #include "authcookie.h"
9    
10     dictionary_tree_t *mulist;
11    
12     /*
13     * myuser_add(char *name, char *pass, char *email, unsigned int flags)
14     *
15     * Creates an account and adds it to the accounts DTree.
16     *
17     * Inputs:
18     * - an account name
19     * - an account password
20     * - an email to associate with the account or NONE
21     * - flags for the account
22     *
23     * Outputs:
24     * - on success, a new myuser_t object (account)
25     * - on failure, NULL.
26     *
27     * Side Effects:
28     * - the created account is added to the accounts DTree,
29     * this may be undesirable for a factory.
30     *
31     * Caveats:
32     * - if nicksvs.no_nick_ownership is not enabled, the caller is
33     * responsible for adding a nick with the same name
34     */
35     myuser_t *
36     myuser_add (char *name, char *pass, char *email, unsigned int flags)
37     {
38     myuser_t *mu;
39     soper_t *soper;
40    
41     return_val_if_fail ((mu = myuser_find (name)) == NULL, mu);
42    
43     if (!(runflags & RF_STARTING))
44     slog (LG_DEBUG, "myuser_add(): %s -> %s", name, email);
45    
46     mu = new myuser_t;
47    
48     strlcpy (mu->name, name, NICKLEN);
49     strlcpy (mu->email, email, EMAILLEN);
50    
51     mu->registered = NOW;
52     mu->flags = flags;
53    
54     /* If it's already crypted, don't touch the password. Otherwise,
55     * use set_password() to initialize it. Why? Because set_password
56     * will move the user to encrypted passwords if possible. That way,
57     * new registers are immediately protected and the database is
58     * immediately converted the first time we start up with crypto.
59     */
60     if (flags & MU_CRYPTPASS)
61     strlcpy (mu->pass, pass, NICKLEN);
62     else
63     set_password (mu, pass);
64    
65     dictionary_add (mulist, mu->name, mu);
66    
67     if ((soper = soper_find_named (mu->name)) != NULL)
68     {
69     slog (LG_DEBUG, "myuser_add(): user `%s' has been declared as soper, activating privileges.", mu->name);
70     soper->myuser = mu;
71     mu->soper = soper;
72     }
73    
74     cnt.myuser++;
75    
76     return mu;
77     }
78    
79     /*
80     * myuser_delete(myuser_t *mu)
81     *
82     * Destroys and removes an account from the accounts DTree.
83     *
84     * Inputs:
85     * - account to destroy
86     *
87     * Outputs:
88     * - nothing
89     *
90     * Side Effects:
91     * - an account is destroyed and removed from the accounts DTree.
92     */
93     void
94     myuser_delete (myuser_t *mu)
95     {
96     myuser_t *successor;
97     mychan_t *mc;
98     user_t *u;
99     node_t *n, *tn;
100     chanacs_t *ca;
101    
102     return_if_fail (mu != NULL);
103    
104     if (!(runflags & RF_STARTING))
105     slog (LG_DEBUG, "myuser_delete(): %s", mu->name);
106    
107     /* log them out */
108     while (!mu->logins.empty ())
109     {
110     u = mu->logins.back ();
111     if (!authservice_loaded || !ircd_on_logout (u->nick, mu->name, NULL))
112     {
113     u->myuser = NULL;
114     mu->logins.erase (u);
115     }
116     }
117    
118     /* kill all their channels and chanacs */
119     LIST_FOREACH_SAFE (n, tn, mu->chanacs.head)
120     {
121     ca = static_cast<chanacs_t *> (n->data);
122     mc = ca->mychan;
123    
124     /* attempt succession */
125     if (mc->founder == mu && (successor = mychan_pick_successor (mc)) != NULL)
126     {
127     snoop (_("SUCCESSION: \2%s\2 -> \2%s\2 from \2%s\2"), successor->name, mc->name, mc->founder->name);
128     slog (LG_REGISTER, "myuser_delete(): giving channel %s to %s (unused %ds, founder %s, chanacs %d)", mc->name, successor->name, NOW - mc->used, mc->founder->name, LIST_LENGTH (&mc->chanacs));
129     if (chansvs.me != NULL)
130     verbose (mc, "Foundership changed to \2%s\2 because \2%s\2 was dropped.", successor->name, mc->founder->name);
131    
132     chanacs_change_simple (mc, successor, NULL, CA_FOUNDER_0, 0);
133     mc->founder = successor;
134    
135     if (chansvs.me != NULL)
136     myuser_notice (chansvs.nick, mc->founder, "You are now founder on \2%s\2 (as \2%s\2).", mc->name, mc->founder->name);
137     }
138    
139     /* no successor found */
140     if (mc->founder == mu)
141     {
142     snoop (_("DELETE: \2%s\2 from \2%s\2"), mc->name, mu->name);
143     slog (LG_REGISTER, "myuser_delete(): deleting channel %s (unused %ds, founder %s, chanacs %d)", mc->name, NOW - mc->used, mc->founder->name, LIST_LENGTH (&mc->chanacs));
144    
145     hook_call_event ("channel_drop", mc);
146     if ((config_options.chan && irccasecmp (mc->name, config_options.chan)) || !config_options.chan)
147     part (mc->name, chansvs.nick);
148     object_unref (mc);
149     }
150     else /* successor found, or not founder in the first place */
151     object_unref (ca);
152     }
153    
154     /* remove them from the soper list */
155     if (soper_find (mu))
156     soper_delete (mu->soper);
157    
158     /* delete the metadata */
159     mu->clear_metadata ();
160    
161     /* kill any authcookies */
162     authcookie_destroy_all (mu);
163    
164     /* delete memos */
165 pippijn 1.2 while (!mu->memos.empty ())
166     {
167     free (mu->memos.back ());
168     mu->memos.pop_back ();
169     }
170 pippijn 1.1
171     /* delete access entries */
172     LIST_FOREACH_SAFE (n, tn, mu->access_list.head) myuser_access_delete (mu, (char *) n->data);
173    
174     /* delete their nicks */
175     LIST_FOREACH_SAFE (n, tn, mu->nicks.head)
176     {
177     object_unref (n->data);
178     }
179    
180     /* mu->name is the index for this dtree */
181     dictionary_delete (mulist, mu->name);
182    
183     delete mu;
184    
185     cnt.myuser--;
186     }
187    
188     /*
189     * myuser_find(const char *name)
190     *
191     * Retrieves an account from the accounts DTree.
192     *
193     * Inputs:
194     * - account name to retrieve
195     *
196     * Outputs:
197     * - account wanted or NULL if it's not in the DTree.
198     *
199     * Side Effects:
200     * - none
201     */
202     myuser_t *
203     myuser_find (const char *name)
204     {
205     return static_cast<myuser_t *> (dictionary_retrieve (mulist, name));
206     }
207    
208     /*
209     * myuser_find_ext(const char *name)
210     *
211     * Same as myuser_find() but with nick group support and undernet-style
212     * `=nick' expansion.
213     *
214     * Inputs:
215     * - account name/nick to retrieve or =nick notation for wanted account.
216     *
217     * Outputs:
218     * - account wanted or NULL if it's not in the DTree.
219     *
220     * Side Effects:
221     * - none
222     */
223     myuser_t *
224     myuser_find_ext (const char *name)
225     {
226     user_t *u;
227     mynick_t *mn;
228    
229     if (name == NULL)
230     return NULL;
231    
232     if (*name == '=')
233     {
234     u = user_find_named (name + 1);
235     return u != NULL ? u->myuser : NULL;
236     }
237     else if (nicksvs.no_nick_ownership)
238     return myuser_find (name);
239     else
240     {
241     mn = mynick_find (name);
242     return mn != NULL ? mn->owner : NULL;
243     }
244     }
245    
246     /*
247     * myuser_notice(char *from, myuser_t *target, char *fmt, ...)
248     *
249     * Sends a notice to all users logged into an account.
250     *
251     * Inputs:
252     * - source of message
253     * - target account
254     * - format of message
255     * - zero+ arguments for the formatter
256     *
257     * Outputs:
258     * - nothing
259     *
260     * Side Effects:
261     * - a notice is sent to all users logged into the account.
262     */
263     void
264     myuser_notice (char *from, myuser_t *target, char *fmt, ...)
265     {
266     va_list ap;
267     char buf[BUFSIZE];
268     myuser_t::login_vector::iterator it, it_end;
269    
270     if (target == NULL)
271     return;
272    
273     /* have to reformat it here, can't give a va_list to notice() :(
274     * -- jilles
275     */
276     va_start (ap, fmt);
277     vsnprintf (buf, BUFSIZE, fmt, ap);
278     va_end (ap);
279    
280     for (it = target->logins.begin (), it_end = target->logins.end (); it != it_end; ++it)
281     notice (from, (*it)->nick, "%s", buf);
282     }
283    
284     /*
285     * myuser_access_verify()
286     *
287     * Inputs:
288     * - user to verify, account to verify against
289     *
290     * Outputs:
291     * - true if user matches an accesslist entry
292     * - false otherwise
293     *
294     * Side Effects:
295     * - last login time updated if user matches
296     */
297     bool
298     myuser_access_verify (user_t *u, myuser_t *mu)
299     {
300     node_t *n;
301     char buf[USERLEN + HOSTLEN];
302     char buf2[USERLEN + HOSTLEN];
303     char buf3[USERLEN + HOSTLEN];
304    
305     if (u == NULL || mu == NULL)
306     {
307     slog (LG_DEBUG, "myuser_access_verify(): invalid parameters: u = %p, mu = %p", u, mu);
308     return false;
309     }
310    
311     if (!use_myuser_access)
312     return false;
313    
314     snprintf (buf, sizeof buf, "%s@%s", u->user, u->vhost);
315     snprintf (buf2, sizeof buf2, "%s@%s", u->user, u->host);
316     snprintf (buf3, sizeof buf3, "%s@%s", u->user, u->ip);
317    
318     LIST_FOREACH (n, mu->access_list.head)
319     {
320     char *entry = (char *) n->data;
321    
322     if (!match (entry, buf) || !match (entry, buf2) || !match (entry, buf3) || !match_cidr (entry, buf3))
323     {
324     mu->lastlogin = NOW;
325     return true;
326     }
327     }
328    
329     return false;
330     }
331    
332     /*
333     * myuser_access_add()
334     *
335     * Inputs:
336     * - account to attach access mask to, access mask itself
337     *
338     * Outputs:
339     * - false: me.mdlimit is reached (too many access entries)
340     * - true : success
341     *
342     * Side Effects:
343     * - an access mask is added to an account.
344     */
345     bool
346     myuser_access_add (myuser_t *mu, char *mask)
347     {
348     node_t *n;
349     char *msk;
350    
351     if (mu == NULL || mask == NULL)
352     {
353     slog (LG_DEBUG, "myuser_access_add(): invalid parameters: mu = %p, mask = %p", mu, mask);
354     return false;
355     }
356    
357     if (LIST_LENGTH (&mu->access_list) > me.mdlimit)
358     {
359     slog (LG_DEBUG, "myuser_access_add(): access entry limit reached for %s", mu->name);
360     return false;
361     }
362    
363     msk = sstrdup (mask);
364     n = node_create ();
365     node_add (msk, n, &mu->access_list);
366    
367     cnt.myuser_access++;
368    
369     return true;
370     }
371    
372     /*
373     * myuser_access_find()
374     *
375     * Inputs:
376     * - account to find access mask in, access mask
377     *
378     * Outputs:
379     * - pointer to found access mask or NULL if not found
380     *
381     * Side Effects:
382     * - none
383     */
384     char *
385     myuser_access_find (myuser_t *mu, char *mask)
386     {
387     node_t *n;
388    
389     if (mu == NULL || mask == NULL)
390     {
391     slog (LG_DEBUG, "myuser_access_find(): invalid parameters: mu = %p, mask = %p", mu, mask);
392     return NULL;
393     }
394    
395     LIST_FOREACH (n, mu->access_list.head)
396     {
397     char *entry = (char *) n->data;
398    
399     if (!strcasecmp (entry, mask))
400     return entry;
401     }
402     return NULL;
403     }
404    
405     /*
406     * myuser_access_delete()
407     *
408     * Inputs:
409     * - account to delete access mask from, access mask itself
410     *
411     * Outputs:
412     * - none
413     *
414     * Side Effects:
415     * - an access mask is added to an account.
416     */
417     void
418     myuser_access_delete (myuser_t *mu, char *mask)
419     {
420     node_t *n, *tn;
421    
422     if (mu == NULL || mask == NULL)
423     {
424     slog (LG_DEBUG, "myuser_access_delete(): invalid parameters: mu = %p, mask = %p", mu, mask);
425     return;
426     }
427    
428     LIST_FOREACH_SAFE (n, tn, mu->access_list.head)
429     {
430     char *entry = (char *) n->data;
431    
432     if (!strcasecmp (entry, mask))
433     {
434     node_del (n, &mu->access_list);
435     node_free (n);
436     free (entry);
437    
438     cnt.myuser_access--;
439    
440     return;
441     }
442     }
443     }