1 /*
2  *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3  *
4  *  Copyright (c) 1997-2021 ircd-hybrid development team
5  *
6  *  This program 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 2 of the License, or
9  *  (at your option) any later version.
10  *
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.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19  *  USA
20  */
21 
22 /*! \file id.c
23  * \brief Contains functions pertaining to SID/UID generation.
24  * \version $Id: id.c 9858 2021-01-01 04:43:42Z michael $
25  */
26 
27 #include "stdinc.h"
28 #include "id.h"
29 #include "irc_string.h"
30 #include "client.h"
31 
32 static char new_uid[TOTALSIDUID + 1];  /* Allow for \0 */
33 
34 bool
valid_sid(const char * sid)35 valid_sid(const char *sid)
36 {
37   if (strlen(sid) != IRC_MAXSID)
38     return false;
39 
40   if (!IsDigit(*sid))
41     return false;
42 
43   for (unsigned int i = 1; i < IRC_MAXSID; ++i)
44     if (!IsUpper(*(sid + i)) && !IsDigit(*(sid + i)))
45       return false;
46 
47   return true;
48 }
49 
50 bool
valid_uid(const char * uid)51 valid_uid(const char *uid)
52 {
53   if (strlen(uid) != TOTALSIDUID)
54     return false;
55 
56   if (!IsDigit(*uid))
57     return false;
58 
59   for (unsigned int i = 1; i < TOTALSIDUID; ++i)
60     if (!IsUpper(*(uid + i)) && !IsDigit(*(uid + i)))
61       return false;
62 
63   return true;
64 }
65 
66 /*
67  * init_uid()
68  *
69  * inputs       - NONE
70  * output       - NONE
71  * side effects - new_uid is filled in with server id portion (sid)
72  *                (first 3 bytes). Rest is filled in with '9'.
73  *
74  */
75 void
init_uid(void)76 init_uid(void)
77 {
78   snprintf(new_uid, sizeof(new_uid), "%s999999", me.id);
79 }
80 
81 /*
82  * add_one_to_uid
83  *
84  * inputs       - index number into new_uid
85  * output       - NONE
86  * side effects - new_uid is incremented by one
87  *                note this is a recursive function
88  */
89 static void
add_one_to_uid(unsigned int i)90 add_one_to_uid(unsigned int i)
91 {
92   if (i < IRC_MAXSID)
93     return;
94 
95   if (new_uid[i] == 'Z')
96     new_uid[i] = '0';
97   else if (new_uid[i] == '9')
98   {
99     new_uid[i] = 'A';
100     add_one_to_uid(i - 1);
101   }
102   else
103     ++new_uid[i];
104 }
105 
106 /*
107  * uid_get
108  *
109  * inputs       - struct Client *
110  * output       - new UID is returned to caller
111  * side effects - new_uid is incremented by one.
112  */
113 const char *
uid_get(void)114 uid_get(void)
115 {
116   add_one_to_uid(TOTALSIDUID - 1);  /* Index from 0 */
117   return new_uid;
118 }
119 
120 void
generate_sid(void)121 generate_sid(void)
122 {
123   unsigned int sid = 0;
124   const char *p;
125 
126   for (p = me.name; *p; ++p)
127     sid = 5 * sid + *p;
128   for (p = me.info; *p; ++p)
129     sid = 5 * sid + *p;
130 
131   snprintf(me.id, IRC_MAXSID + 1, "%03d", sid % 1000);
132 }
133