--- /dev/null
+/*
+ * Copyright (c) 2000
+ * Traakan, Inc., Los Altos, CA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Project: NDMJOB
+ * Ident: $Id: $
+ *
+ * Description:
+ *
+ * MD5 authentication support
+ ****************************************************************
+ * Both sides share a secret in the form of a clear-text
+ * password. One side generates a challenge (64-bytes)
+ * and conveys it to the other. The other side then
+ * uses the challenge, the clear-text password, and
+ * the NDMP rules for MD5, and generates a digest.
+ * The digest is returned as proof that both sides
+ * share the same secret clear-text password.
+ *
+ * The NDMP rules for MD5 are implemented in ndmmd5_digest().
+ * It amounts to positioning the clear-text password and challenge
+ * into a "message" buffer, then applying the MD5 algorithm.
+ *
+ * ndmmd5_generate_challenge() generates a challenge[]
+ * using conventional random number routines.
+ *
+ * ndmmd5_ok_digest() takes a locally known challenge[]
+ * and clear-text password, a remotely generated
+ * digest[], and determines if everything is correct.
+ *
+ * Using MD5 prevents clear-text passwords from being conveyed
+ * over the network. However, it compels both sides to maintain
+ * clear-text passwords in a secure fashion, which is difficult
+ * to say the least. Because the NDMP MD5 rules must be followed
+ * to digest() the password, it's impractical to consider
+ * an external authentication authority.
+ *
+ * Credits to Rajiv of NetApp for helping with MD5 stuff.
+ */
+
+
+#include "ndmlib.h"
+#include "md5.h"
+
+
+int
+ndmmd5_generate_challenge (char challenge[NDMP_MD5_CHALLENGE_LENGTH])
+{
+ int i;
+
+ NDMOS_MACRO_SRAND();
+
+ for (i = 0; i < NDMP_MD5_CHALLENGE_LENGTH; i++) {
+ challenge[i] = NDMOS_MACRO_RAND() >> (i&7);
+ }
+
+ return 0;
+}
+
+
+int
+ndmmd5_ok_digest (char challenge[NDMP_MD5_CHALLENGE_LENGTH],
+ char *clear_text_password,
+ char digest[NDMP_MD5_DIGEST_LENGTH])
+{
+ char my_digest[16];
+ int i;
+
+ ndmmd5_digest (challenge, clear_text_password, my_digest);
+
+ for (i = 0; i < NDMP_MD5_DIGEST_LENGTH; i++)
+ if (digest[i] != my_digest[i])
+ return 0; /* Invalid */
+
+ return 1; /* OK */
+}
+
+
+int
+ndmmd5_digest (char challenge[NDMP_MD5_CHALLENGE_LENGTH],
+ char *clear_text_password,
+ char digest[NDMP_MD5_DIGEST_LENGTH])
+{
+ int pwlength = strlen (clear_text_password);
+ MD5_CTX mdContext;
+ unsigned char message[128];
+
+ /*
+ * The spec describes the construction of the 128 byte
+ * "message" (probably MD5-speak). It is described as:
+ *
+ * PASSWORD PADDING CHALLENGE PADDING PASSWORD
+ *
+ * Each PADDING is defined as zeros of length 64 minus pwlen.
+ *
+ * A pwlen of over 32 would result in not all fields
+ * fitting. This begs a question of the order elements
+ * are inserted into the message[]. You get a different
+ * message[] if you insert the PASSWORD(s) before
+ * the CHALLENGE than you get the other way around.
+ *
+ * A pwlen of over 64 would result in PADDING of negative
+ * length, which could cause crash boom bang.
+ *
+ * The resolution of this vaguery implemented here is to
+ * only use the first 32 bytes of the password. All
+ * fields fit. Order dependencies are avoided.
+ *
+ * Final resolution is pending.
+ */
+ if (pwlength > 32)
+ pwlength = 32;
+
+ /*
+ * Compose the 128-byte buffer according to NDMP rules
+ */
+ NDMOS_API_BZERO (message, sizeof message);
+ NDMOS_API_BCOPY (clear_text_password, &message[0], pwlength);
+ NDMOS_API_BCOPY (clear_text_password,
+ &message[128 - pwlength], pwlength);
+ NDMOS_API_BCOPY (challenge, &message[64 - pwlength], 64);
+
+ /*
+ * Grind it up, ala MD5
+ */
+ MD5Init(&mdContext);
+ MD5Update(&mdContext, message, 128);
+ MD5Final((unsigned char *)digest, &mdContext);
+
+ /*
+ * ding! done
+ */
+ return 0;
+}