2 * rlm_ns_mta_md5.c Functions to authenticate using NS-MTA-MD5 passwords.
3 * Taken from the hacks for qmail located at nrg4u.com
6 * NS-MTA-MD5 passwords are 64 byte strings, the first
7 * 32 bytes being the password hash and the last 32 bytes
8 * the salt. The clear text password and the salt are MD5
9 * hashed[1]. If the resulting hash concatenated with the salt
10 * are equivalent to the original NS-MTA-MD5 password the
11 * password is correct.
13 * [1] Read the source for details.
15 * bob Auth-Type := NS-MTA-MD5, NS-MTA-MD5-Password := "f8b4eac9f051a61eebe266f9c29a193626d8eb25c2598c55c8874260b24eb435"
16 * Reply-Message = "NS-MTA-MD5 is working!"
17 * password = "testpass".
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License as published by
23 * the Free Software Foundation; either version 2 of the License, or
24 * (at your option) any later version.
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35 * Copyright 2000 The FreeRADIUS server project
36 * Copyright 2000 Andre Oppermann
40 static const char rcsid[] = "$Id$";
54 static const char *ns_mta_hextab = "0123456789abcdef";
57 * Smaller & faster than snprintf("%x");
59 static void ns_mta_hexify(char *buffer, char *str, int len)
65 for(i = 0;i < len; i ++) {
67 buffer[2*i] = ns_mta_hextab[(ch>>4) & 15];
68 buffer[2*i + 1] = ns_mta_hextab[ch & 15];
76 static char *ns_mta_hash_alg(char *buffer, const char *salt, const char *passwd)
80 unsigned char digest[16];
82 snprintf(saltstr, sizeof(saltstr), "%s%c%s%c%s",salt, 89, passwd, 247, salt);
85 MD5Update(&context,(unsigned char *)saltstr,strlen(saltstr));
86 MD5Final(digest,&context);
87 ns_mta_hexify(buffer,(char*)digest,16);
95 static int ns_mta_md5_pass(const char *clear, const char *encrypted)
97 char hashed[HASH_LEN];
100 if (!(strlen(encrypted) == 64)) {
101 DEBUG2("NS-MTA-MD5 hash not 64 bytes");
105 memcpy(salt, &encrypted[32], 32);
107 ns_mta_hash_alg(hashed, salt, clear);
108 memcpy(&hashed[32], salt, 33);
110 if (strcasecmp(hashed,encrypted) == 0) {
118 * Validate User-Name / Passwd
120 static int module_auth(void *instance, REQUEST *request)
122 VALUE_PAIR *md5_password;
125 * We can only authenticate user requests which HAVE
126 * a User-Password attribute.
128 if (!request->password) {
129 radlog(L_AUTH, "rlm_ns_mta_md5: Attribute \"User-Password\" is required for authentication.");
130 return RLM_MODULE_INVALID;
134 * Ensure that we're being passed a plain-text password,
135 * and not anything else.
137 if (request->password->attribute != PW_PASSWORD) {
138 radlog(L_AUTH, "rlm_ns_mta_md5: Attribute \"User-Password\" is required for authentication. Cannot use \"%s\".", request->password->name);
139 return RLM_MODULE_INVALID;
143 * Find the MD5 encrypted password
145 md5_password = pairfind(request->config_items, PW_NS_MTA_MD5_PASSWORD);
147 radlog(L_AUTH, "rlm_ns_mta_md5: Cannot find NS-MTA-MD5-Password attribute.");
148 return RLM_MODULE_INVALID;
152 * Check their password against the encrypted one.
154 if (ns_mta_md5_pass(request->password->strvalue,
155 md5_password->strvalue) < 0) {
156 return RLM_MODULE_REJECT;
159 return RLM_MODULE_OK;
162 module_t rlm_ns_mta_md5 = {
164 0, /* type: reserved */
165 NULL, /* initialize */
166 NULL, /* instantiation */
168 module_auth, /* authenticate */
169 NULL, /* authorize */
170 NULL, /* pre-accounting */
171 NULL, /* accounting */
172 NULL, /* checksimul */
173 NULL, /* pre-proxy */
174 NULL, /* post-proxy */