3 * Traakan, Inc., Los Altos, CA
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice unmodified, this list of conditions, and the following
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * MD5 authentication support
36 ****************************************************************
37 * Both sides share a secret in the form of a clear-text
38 * password. One side generates a challenge (64-bytes)
39 * and conveys it to the other. The other side then
40 * uses the challenge, the clear-text password, and
41 * the NDMP rules for MD5, and generates a digest.
42 * The digest is returned as proof that both sides
43 * share the same secret clear-text password.
45 * The NDMP rules for MD5 are implemented in ndmmd5_digest().
46 * It amounts to positioning the clear-text password and challenge
47 * into a "message" buffer, then applying the MD5 algorithm.
49 * ndmmd5_generate_challenge() generates a challenge[]
50 * using conventional random number routines.
52 * ndmmd5_ok_digest() takes a locally known challenge[]
53 * and clear-text password, a remotely generated
54 * digest[], and determines if everything is correct.
56 * Using MD5 prevents clear-text passwords from being conveyed
57 * over the network. However, it compels both sides to maintain
58 * clear-text passwords in a secure fashion, which is difficult
59 * to say the least. Because the NDMP MD5 rules must be followed
60 * to digest() the password, it's impractical to consider
61 * an external authentication authority.
63 * Credits to Rajiv of NetApp for helping with MD5 stuff.
72 ndmmd5_generate_challenge (char challenge[NDMP_MD5_CHALLENGE_LENGTH])
78 for (i = 0; i < NDMP_MD5_CHALLENGE_LENGTH; i++) {
79 challenge[i] = NDMOS_MACRO_RAND() >> (i&7);
87 ndmmd5_ok_digest (char challenge[NDMP_MD5_CHALLENGE_LENGTH],
88 char *clear_text_password,
89 char digest[NDMP_MD5_DIGEST_LENGTH])
94 ndmmd5_digest (challenge, clear_text_password, my_digest);
96 for (i = 0; i < NDMP_MD5_DIGEST_LENGTH; i++)
97 if (digest[i] != my_digest[i])
98 return 0; /* Invalid */
105 ndmmd5_digest (char challenge[NDMP_MD5_CHALLENGE_LENGTH],
106 char *clear_text_password,
107 char digest[NDMP_MD5_DIGEST_LENGTH])
109 int pwlength = strlen (clear_text_password);
111 unsigned char message[128];
114 * The spec describes the construction of the 128 byte
115 * "message" (probably MD5-speak). It is described as:
117 * PASSWORD PADDING CHALLENGE PADDING PASSWORD
119 * Each PADDING is defined as zeros of length 64 minus pwlen.
121 * A pwlen of over 32 would result in not all fields
122 * fitting. This begs a question of the order elements
123 * are inserted into the message[]. You get a different
124 * message[] if you insert the PASSWORD(s) before
125 * the CHALLENGE than you get the other way around.
127 * A pwlen of over 64 would result in PADDING of negative
128 * length, which could cause crash boom bang.
130 * The resolution of this vaguery implemented here is to
131 * only use the first 32 bytes of the password. All
132 * fields fit. Order dependencies are avoided.
134 * Final resolution is pending.
140 * Compose the 128-byte buffer according to NDMP rules
142 NDMOS_API_BZERO (message, sizeof message);
143 NDMOS_API_BCOPY (clear_text_password, &message[0], pwlength);
144 NDMOS_API_BCOPY (clear_text_password,
145 &message[128 - pwlength], pwlength);
146 NDMOS_API_BCOPY (challenge, &message[64 - pwlength], 64);
149 * Grind it up, ala MD5
152 MD5Update(&mdContext, message, 128);
153 MD5Final((unsigned char *)digest, &mdContext);