2 * Challenge Response Authentication Method using MD5 (CRAM-MD5)
4 * cram-md5 is based on RFC2104.
6 * Written for Bacula by Kern E. Sibbald, May MMI.
11 Copyright (C) 2000-2004 Kern Sibbald and John Walker
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Lesser General Public
15 License as published by the Free Software Foundation; either
16 version 2.1 of the License, or (at your option) any later version.
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, write to the Free
25 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
32 /* Authorize other end */
33 int cram_md5_auth(BSOCK *bs, char *password, int ssl_need)
43 gettimeofday(&t1, &tz);
45 gettimeofday(&t2, &tz);
47 srandom((t1.tv_sec&0xffff) * (t2.tv_usec&0xff));
48 if (!gethostname(host, sizeof(host))) {
49 bstrncpy(host, my_name, sizeof(host));
51 bsnprintf(chal, sizeof(chal), "<%u.%u@%s>", (uint32_t)random(), (uint32_t)time(NULL), host);
52 Dmsg2(50, "send: auth cram-md5 %s ssl=%d\n", chal, ssl_need);
53 if (!bnet_fsend(bs, "auth cram-md5 %s ssl=%d\n", chal, ssl_need)) {
54 Dmsg1(50, "Bnet send challenge error.\n", bnet_strerror(bs));
58 if (!bnet_ssl_client(bs, password, ssl_need)) {
61 if (bnet_wait_data(bs, 180) <= 0 || bnet_recv(bs) <= 0) {
62 Dmsg1(50, "Bnet receive challenge response error.\n", bnet_strerror(bs));
66 hmac_md5((uint8_t *)chal, strlen(chal), (uint8_t *)password, strlen(password), hmac);
67 bin_to_base64(host, (char *)hmac, 16);
68 ok = strcmp(bs->msg, host) == 0;
70 Dmsg1(50, "Authenticate OK %s\n", host);
72 Dmsg2(50, "Authenticate NOT OK: wanted %s, got %s\n", host, bs->msg);
75 bnet_fsend(bs, "1000 OK auth\n");
77 Dmsg1(50, "Auth failed PW: %s\n", password);
78 bnet_fsend(bs, "1999 Authorization failed.\n");
84 /* Get authorization from other end */
85 int cram_md5_get_auth(BSOCK *bs, char *password, int ssl_need)
89 int ssl_has; /* This is what the other end has */
91 if (bnet_recv(bs) <= 0) {
95 if (bs->msglen >= MAXSTRING) {
96 Dmsg1(50, "Msg too long wanted auth cram... Got: %s", bs->msg);
100 Dmsg1(100, "cram-get: %s", bs->msg);
101 if (sscanf(bs->msg, "auth cram-md5 %s ssl=%d\n", chal, &ssl_has) != 2) {
102 ssl_has = BNET_SSL_NONE;
103 if (sscanf(bs->msg, "auth cram-md5 %s\n", chal) != 1) {
104 Dmsg1(50, "Cannot scan challenge: %s", bs->msg);
105 bnet_fsend(bs, "1999 Authorization failed.\n");
110 if (!bnet_ssl_server(bs, password, ssl_need, ssl_has)) {
114 hmac_md5((uint8_t *)chal, strlen(chal), (uint8_t *)password, strlen(password), hmac);
115 bs->msglen = bin_to_base64(bs->msg, (char *)hmac, 16) + 1;
116 if (!bnet_send(bs)) {
117 Dmsg1(50, "Send challenge failed. ERR=%s\n", bnet_strerror(bs));
120 Dmsg1(99, "sending resp to challenge: %s\n", bs->msg);
121 if (bnet_wait_data(bs, 180) <= 0 || bnet_recv(bs) <= 0) {
122 Dmsg1(50, "Receive chanllenge response failed. ERR=%s\n", bnet_strerror(bs));
126 if (strcmp(bs->msg, "1000 OK auth\n") == 0) {
129 Dmsg1(50, "Bad auth response: %s\n", bs->msg);