2 * IRC - Internet Relay Chat, ircd/umkpasswd.c
3 * Copyright (C) 2002 hikari
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 1, or (at your option)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 /* #include <assert.h> -- Now using assert in ircd_log.h */
33 #include "ircd_alloc.h"
34 #include "ircd_log.h" /* for ircd's assert.h */
35 #include "ircd_string.h"
36 #include "umkpasswd.h"
40 /* crypto mech headers */
41 #include "ircd_crypt.h"
42 #include "ircd_crypt_smd5.h"
43 #include "ircd_crypt_native.h"
44 #include "ircd_crypt_plain.h"
46 /* bleah, evil globals */
47 umkpasswd_conf_t* umkpasswd_conf;
48 crypt_mechs_t* crypt_mechs_root;
52 void sendto_opmask_butone(struct Client *one, unsigned int mask,
53 const char *pattern, ...)
55 /* only needed with memdebug, which also calls Debug() */
60 fprintf(stderr, "umkpasswd - Copyright (c) 2002 hikari\n");
67 char *debughelp = "[-d <level>] ";
73 /*fprintf(stderr, "umkpasswd [-l] [[[-a]||[-u]] <username>] [-y <class>] %s[-c <file>] -m <mech> [password]\n\n", debughelp);*/
74 fprintf(stderr, "umkpasswd [-l] %s-m <mech> [password]\n\n", debughelp);
75 fprintf(stderr, " -l List mechanisms available.\n");
77 fprintf(stderr, " -a <user> Add user to conf file.\n");
78 fprintf(stderr, " -u <user> Update user's password field.\n");
79 fprintf(stderr, " -y <class> Class to place oper in.\n");
81 fprintf(stderr, " -m <mech> Mechanism to use [MANDATORY].\n");
83 fprintf(stderr, " -d <level> Debug level to run at.\n");
86 fprintf(stderr, " -c <file> Conf file to use, default is DPATH/CPATH.\n\n");
91 /* our implementation of debug() */
92 void debug(int level, const char *form, ...)
97 if (level <= (umkpasswd_conf->debuglevel))
100 vfprintf(stderr, form, vl);
101 fprintf(stderr, "\n");
107 /* quick implementation of log_write() for assert() call */
108 void log_write(enum LogSys subsys, enum LogLevel severity,
109 unsigned int flags, const char *fmt, ...)
113 vfprintf(stderr, fmt, vl);
114 fprintf(stderr, "\n");
118 /* quick and dirty salt generator */
119 char *make_salt(const char *salts)
124 /* try and get around them running this time after time in quick succession */
126 srandom((unsigned int)time(NULL));
128 if((tmp = calloc(3, sizeof(char))) != NULL)
130 /* can't optimize this much more than just doing it twice */
131 n = ((float)(strlen(salts))*random()/(RAND_MAX+1.0));
132 memcpy(tmp, (salts+n), 1);
134 n = ((float)(strlen(salts))*random()/(RAND_MAX+1.0));
135 memcpy((tmp+1), (salts+n), 1);
137 Debug((DEBUG_DEBUG, "salts = %s", salts));
138 Debug((DEBUG_DEBUG, "strlen(salts) = %d", strlen(salts)));
144 /* our implementation of ircd_crypt_register_mech() */
145 int ircd_crypt_register_mech(crypt_mech_t* mechanism)
147 crypt_mechs_t* crypt_mech;
149 Debug((DEBUG_INFO, "ircd_crypt_register_mech: registering mechanism: %s", mechanism->shortname));
151 /* try to allocate some memory for the new mechanism */
152 if ((crypt_mech = (crypt_mechs_t*)MyMalloc(sizeof(crypt_mechs_t))) == NULL)
154 /* aww poot, we couldn't get any memory, scream a little then back out */
155 Debug((DEBUG_MALLOC, "ircd_crypt_register_mech: could not allocate memory for %s", mechanism->shortname));
159 /* ok, we have memory, initialise it */
160 memset(crypt_mech, 0, sizeof(crypt_mechs_t));
162 /* assign the data */
163 crypt_mech->mech = mechanism;
164 crypt_mech->next = crypt_mech->prev = NULL;
166 /* first of all, is there anything there already? */
167 if(crypt_mechs_root->next == NULL)
169 /* nope, just add ourself */
170 crypt_mechs_root->next = crypt_mechs_root->prev = crypt_mech;
172 /* nice and simple, put ourself at the end */
173 crypt_mech->prev = crypt_mechs_root->prev;
174 crypt_mech->next = NULL;
175 crypt_mechs_root->prev = crypt_mech->prev->next = crypt_mech;
179 Debug((DEBUG_INFO, "ircd_crypt_register_mech: registered mechanism: %s, crypt_function is at 0x%X.", crypt_mech->mech->shortname, &crypt_mech->mech->crypt_function));
180 Debug((DEBUG_INFO, "ircd_crypt_register_mech: %s: %s", crypt_mech->mech->shortname, crypt_mech->mech->description));
191 unsigned char buffer[1024], digest[16], vstr[32];
194 str = tmp + strlen(tmp);
195 while (str[-1] == '\r' || str[-1] == '\n') *--str = '\0';
196 if (NULL == (file = fopen(tmp, "r")))
198 fprintf(stderr, "unable to open %s: %s", tmp, strerror(errno));
202 while ((fgets((char*)buffer, sizeof(buffer), file)) != NULL)
204 MD5Update(&context, buffer, strlen((char*)buffer));
205 str = strstr((char*)buffer, "$Id: ");
208 for (str += 5; !isspace(*str); ++str) {}
209 while (isspace(*++str)) {}
210 for (len = 0; !isspace(str[len]); ++len) vstr[len] = str[len];
215 while ((len = fread (buffer, 1, sizeof(buffer), file)))
216 MD5Update(&context, buffer, len);
217 MD5Final(digest, &context);
220 str = strrchr(tmp, '/');
221 printf(" \"[ %s: ", str ? (str + 1) : tmp);
222 for (len = 0; len < 16; len++)
223 printf ("%02x", digest[len]);
224 printf(" %s ]\",\n", vstr);
227 /* dump the loaded mechs list */
228 void show_mechs(void)
230 crypt_mechs_t* mechs;
233 printf("\nAvailable mechanisms:\n");
235 if(crypt_mechs_root == NULL)
238 mechs = crypt_mechs_root->next;
245 printf(" %s\t\t%s\n", mechs->mech->mechname, mechs->mech->description);
251 /* load in the mech "modules" */
252 void load_mechs(void)
254 /* we need these loaded by hand for now */
256 ircd_register_crypt_native();
257 ircd_register_crypt_smd5();
258 ircd_register_crypt_plain(); /* yes I know it's slightly pointless */
263 crypt_mechs_t* hunt_mech(const char* mechname)
267 assert(NULL != mechname);
269 if(crypt_mechs_root == NULL)
272 mech = crypt_mechs_root->next;
279 if(0 == (ircd_strcmp(mech->mech->mechname, mechname)))
286 char* crypt_pass(const char* pw, const char* mech)
288 crypt_mechs_t* crypt_mech;
289 char* salt, *untagged, *tagged;
292 assert(NULL != mech);
294 Debug((DEBUG_DEBUG, "pw = %s\n", pw));
295 Debug((DEBUG_DEBUG, "mech = %s\n", mech));
297 if (NULL == (crypt_mech = hunt_mech(mech)))
299 printf("Unable to find mechanism %s\n", mech);
303 salt = make_salt(default_salts);
305 untagged = (char *)CryptFunc(crypt_mech->mech)(pw, salt);
306 tagged = (char *)MyMalloc(strlen(untagged)+CryptTokSize(crypt_mech->mech)+1);
307 memset(tagged, 0, strlen(untagged)+CryptTokSize(crypt_mech->mech)+1);
308 strncpy(tagged, CryptTok(crypt_mech->mech), CryptTokSize(crypt_mech->mech));
309 strncpy(tagged+CryptTokSize(crypt_mech->mech), untagged, strlen(untagged));
314 char* parse_arguments(int argc, char **argv)
317 const char* options = "a:d:lm:u:y:5";
319 umkpasswd_conf = (umkpasswd_conf_t*)MyMalloc(sizeof(umkpasswd_conf_t));
321 umkpasswd_conf->flags = 0;
322 umkpasswd_conf->debuglevel = 0;
323 umkpasswd_conf->operclass = 0;
324 umkpasswd_conf->user = NULL;
325 umkpasswd_conf->mech = NULL;
328 len = strlen(DPATH) + strlen(CPATH) + 2;
329 umkpasswd_conf->conf = (char *)MyMalloc(len*sizeof(char));
330 memset(umkpasswd_conf->conf, 0, len*sizeof(char));
331 ircd_strncpy(umkpasswd_conf->conf, DPATH, strlen(DPATH));
332 *((umkpasswd_conf->conf) + strlen(DPATH)) = '/';
333 ircd_strncpy((umkpasswd_conf->conf) + strlen(DPATH) + 1, CPATH, strlen(CPATH));
337 while ((EOF != (c = getopt(argc, argv, options))) && !len)
344 while (fgets(t1, sizeof(t1), stdin)) sum(t1);
349 umkpasswd_conf->operclass = atoi(optarg);
350 if (umkpasswd_conf->operclass < 0)
351 umkpasswd_conf->operclass = 0;
355 if(umkpasswd_conf->flags & ACT_ADDOPER)
357 fprintf(stderr, "-a and -u are mutually exclusive. Use either or neither.\n");
358 abort(); /* b0rk b0rk b0rk */
361 umkpasswd_conf->flags |= ACT_UPDOPER;
362 umkpasswd_conf->user = optarg;
366 umkpasswd_conf->mech = optarg;
376 umkpasswd_conf->debuglevel = atoi(optarg);
377 if (umkpasswd_conf->debuglevel < 0)
378 umkpasswd_conf->debuglevel = 0;
382 umkpasswd_conf->conf = optarg;
386 if(umkpasswd_conf->flags & ACT_UPDOPER)
388 fprintf(stderr, "-a and -u are mutually exclusive. Use either or neither.\n");
389 abort(); /* b0rk b0rk b0rk */
392 umkpasswd_conf->flags |= ACT_ADDOPER;
393 umkpasswd_conf->user = optarg;
397 /* unknown option - spit out syntax and b0rk */
404 Debug((DEBUG_DEBUG, "flags = %d", umkpasswd_conf->flags));
405 Debug((DEBUG_DEBUG, "operclass = %d", umkpasswd_conf->operclass));
406 Debug((DEBUG_DEBUG, "debug = %d", umkpasswd_conf->debuglevel));
408 if (NULL != umkpasswd_conf->mech)
409 Debug((DEBUG_DEBUG, "mech = %s", umkpasswd_conf->mech));
411 Debug((DEBUG_DEBUG, "mech is unset"));
413 if (NULL != umkpasswd_conf->conf)
414 Debug((DEBUG_DEBUG, "conf = %s", umkpasswd_conf->conf));
416 Debug((DEBUG_DEBUG, "conf is unset"));
418 if (NULL != umkpasswd_conf->user)
419 Debug((DEBUG_DEBUG, "user = %s", umkpasswd_conf->user));
421 Debug((DEBUG_DEBUG, "user is unset"));
423 /* anything left over should be password */
427 int main(int argc, char **argv)
429 char* pw, *crypted_pw;
431 crypt_mechs_root = (crypt_mechs_t*)MyMalloc(sizeof(crypt_mechs_t));
432 crypt_mechs_root->mech = NULL;
433 crypt_mechs_root->next = crypt_mechs_root->prev = NULL;
441 pw = parse_arguments(argc, argv);
444 if (NULL == umkpasswd_conf->mech)
446 fprintf(stderr, "No mechanism specified.\n");
452 pw = getpass("Password: ");
454 crypted_pw = crypt_pass(pw, umkpasswd_conf->mech);
456 printf("Crypted Pass: %s\n", crypted_pw);
457 memset(pw, 0, strlen(pw));