]>
jfr.im git - irc/quakenet/snircd.git/blob - ircd/ircd_crypt.c
2 * IRC - Internet Relay Chat, ircd/ircd_crypt.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.
23 * @brief Core password encryption routines.
24 * @version $Id: ircd_crypt.c,v 1.7 2005/06/24 13:57:21 a1kmm Exp $
26 * This is a new look crypto API for ircu, it can handle different
27 * password formats by the grace of magic tokens at the beginning of the
28 * password e.g. $SMD5 for Salted MD5, $CRYPT for native crypt(), etc.
30 * Currently crypt routines are implemented for: the native crypt()
31 * function, Salted MD5 and a plain text mechanism which should only
32 * be used for testing. I intend to add Blowfish, 3DES and possibly
33 * SHA1 support as well at some point, but I'll need to check the
34 * possible problems that'll cause with stupid crypto laws.
36 * It's also designed to be "ready" for the modularisation of ircu, so
37 * someone get round to doing it, because I'm not doing it ;)
39 * The plan for Stage B is to semi-modularise the authentication
40 * mechanism to allow authentication against some other sources than
41 * the conf file (whatever takes someones fancy, kerberos, ldap, sql, etc).
43 * -- blessed be, hikari.
47 #include "ircd_crypt.h"
48 #include "ircd_alloc.h"
49 #include "ircd_features.h"
51 #include "ircd_string.h"
54 /* while we're not modular, we need their init functions */
55 #include "ircd_crypt_native.h"
56 #include "ircd_crypt_plain.h"
57 #include "ircd_crypt_smd5.h"
59 /* #include <assert.h> -- Now using assert in ircd_log.h */
64 crypt_mechs_t
* crypt_mechs_root
;
66 /** Add a crypt mechanism to the list
67 * @param mechanism Pointer to the mechanism details struct
68 * @return 0 on success, anything else on fail.
70 * This routine registers a new crypt mechanism in the loaded mechanisms list,
71 * making it availabe for comparing passwords.
73 int ircd_crypt_register_mech ( crypt_mech_t
* mechanism
)
75 crypt_mechs_t
* crypt_mech
;
77 Debug (( DEBUG_INFO
, "ircd_crypt_register_mech: registering mechanism: %s " , mechanism
-> shortname
));
79 /* try to allocate some memory for the new mechanism */
80 if (( crypt_mech
= ( crypt_mechs_t
*) MyMalloc ( sizeof ( crypt_mechs_t
))) == NULL
)
82 /* aww poot, we couldn't get any memory, scream a little then back out */
83 Debug (( DEBUG_MALLOC
, "ircd_crypt_register_mech: could not allocate memory for %s " , mechanism
-> shortname
));
87 /* ok, we have memory, initialise it */
88 memset ( crypt_mech
, 0 , sizeof ( crypt_mechs_t
));
91 crypt_mech
-> mech
= mechanism
;
92 crypt_mech
-> next
= crypt_mech
-> prev
= NULL
;
94 /* first of all, is there anything there already? */
95 if ( crypt_mechs_root
-> next
== NULL
)
97 /* nope, just add ourself */
98 crypt_mechs_root
-> next
= crypt_mechs_root
-> prev
= crypt_mech
;
100 /* nice and simple, put ourself at the end */
101 crypt_mech
-> prev
= crypt_mechs_root
-> prev
;
102 crypt_mech
-> next
= NULL
;
103 crypt_mechs_root
-> prev
= crypt_mech
-> prev
-> next
= crypt_mech
;
107 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
));
108 Debug (( DEBUG_INFO
, "ircd_crypt_register_mech: %s : %s " , crypt_mech
-> mech
-> shortname
, crypt_mech
-> mech
-> description
));
112 /** Remove a crypt mechanism from the list
113 * @param mechanism Pointer to the mechanism we want to remove
114 * @return 0 on success, anything else on fail.
116 int ircd_crypt_unregister_mech ( crypt_mech_t
* mechanism
)
122 /** Wrapper for generating a hashed password passed on the supplied password
123 * @param key Pointer to the password we want crypted
124 * @param salt Pointer to the password we're comparing to (for the salt)
125 * @return Pointer to the generated password (must be MyFree()'d).
127 * This is a wrapper function which attempts to establish the password
128 * format and funnel it off to the correct mechanism handler function. The
129 * returned password is compared in the oper_password_match() routine.
131 char * ircd_crypt ( const char * key
, const char * salt
)
133 char * hashed_pass
= NULL
;
134 const char * temp_hashed_pass
, * mysalt
;
135 crypt_mechs_t
* crypt_mech
;
138 assert ( NULL
!= salt
);
140 Debug (( DEBUG_DEBUG
, "ircd_crypt: key is %s " , key
));
141 Debug (( DEBUG_DEBUG
, "ircd_crypt: salt is %s " , salt
));
143 crypt_mech
= crypt_mechs_root
-> next
;
145 /* by examining the first n characters of a password string we
146 * can discover what kind of password it is. hopefully. */
149 if ( strlen ( salt
) < crypt_mech
-> mech
-> crypt_token_size
)
151 /* try the next mechanism instead */
152 Debug (( DEBUG_DEBUG
, "ircd_crypt: salt is too short, will try next mech at 0x %X " , crypt_mech
-> next
));
153 crypt_mech
= crypt_mech
-> next
;
157 Debug (( DEBUG_DEBUG
, "ircd_crypt: comparing %s with %s " ,
158 salt
, crypt_mech
-> mech
-> crypt_token
));
160 if ( 0 == ircd_strncmp ( crypt_mech
-> mech
-> crypt_token
, salt
, crypt_mech
-> mech
-> crypt_token_size
))
162 Debug (( DEBUG_DEBUG
, "ircd_crypt: type is %s " ,
163 crypt_mech
-> mech
-> shortname
));
165 /* before we send this all off to the crypt_function, we need to remove
168 /* make sure we won't end up with a password comprised entirely of
170 if ( strlen ( salt
) < crypt_mech
-> mech
-> crypt_token_size
+ 1 )
173 mysalt
= salt
+ crypt_mech
-> mech
-> crypt_token_size
;
175 if ( NULL
== ( temp_hashed_pass
= crypt_mech
-> mech
-> crypt_function ( key
, mysalt
)))
178 Debug (( DEBUG_DEBUG
, "ircd_crypt: untagged pass is %s " , temp_hashed_pass
));
180 /* ok, now we need to prefix the password we just got back
181 with the right tag */
182 if ( NULL
== ( hashed_pass
= ( char *) MyMalloc ( sizeof ( char )* strlen ( temp_hashed_pass
) + crypt_mech
-> mech
-> crypt_token_size
+ 1 )))
184 Debug (( DEBUG_MALLOC
, "ircd_crypt: unable to allocate memory for temp_hashed_pass" ));
187 memset ( hashed_pass
, 0 , sizeof ( char )* strlen ( temp_hashed_pass
)
188 + crypt_mech
-> mech
-> crypt_token_size
+ 1 );
189 ircd_strncpy ( hashed_pass
, crypt_mech
-> mech
-> crypt_token
,
190 crypt_mech
-> mech
-> crypt_token_size
);
191 ircd_strncpy ( hashed_pass
+ crypt_mech
-> mech
-> crypt_token_size
, temp_hashed_pass
, strlen ( temp_hashed_pass
));
192 Debug (( DEBUG_DEBUG
, "ircd_crypt: tagged pass is %s " , hashed_pass
));
194 Debug (( DEBUG_DEBUG
, "ircd_crypt: will try next mechanism at 0x %X " ,
196 crypt_mech
= crypt_mech
-> next
;
202 /* try to use native crypt for an old-style (untagged) password */
203 if ( strlen ( salt
) > 2 )
206 temp_hashed_pass
= ( char *) ircd_crypt_native ( key
, salt
);
207 if (! ircd_strcmp ( temp_hashed_pass
, salt
))
209 DupString ( s
, temp_hashed_pass
);
218 * This function loads initalises the crypt mechanisms linked list and
219 * currently loads the default mechanisms (Salted MD5, Crypt() and PLAIN).
220 * The last step is only needed while ircu is not properly modular.
222 * When ircu is modular this will be the entry function for the ircd_crypt
226 void ircd_crypt_init ( void )
229 if (( crypt_mechs_root
= MyMalloc ( sizeof ( crypt_mechs_t
))) == NULL
)
231 /* awooga - can't allocate memory for the root structure */
232 Debug (( DEBUG_MALLOC
, "init_crypt: Could not allocate memory for crypt_mechs_root" ));
236 crypt_mechs_root
-> mech
= NULL
;
237 crypt_mechs_root
-> next
= crypt_mechs_root
-> prev
= NULL
;
239 /* temporary kludge until we're modular. manually call the
240 register functions for crypt mechanisms */
241 ircd_register_crypt_smd5 ();
242 ircd_register_crypt_plain ();
243 ircd_register_crypt_native ();