1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
/* ntlm.h -- interface declarations for SMB authentication code */
#include "smbtypes.h"
/*
* These structures are byte-order dependant, and should not
* be manipulated except by the use of the routines provided
*/
typedef struct
{
uint16 len;
uint16 maxlen;
uint32 offset;
}tSmbStrHeader;
typedef struct
{
char ident[8];
uint32 msgType;
uint32 flags;
tSmbStrHeader user;
tSmbStrHeader domain;
uint8 buffer[1024];
uint32 bufIndex;
}tSmbNtlmAuthRequest;
typedef struct
{
char ident[8];
uint32 msgType;
tSmbStrHeader uDomain;
uint32 flags;
uint8 challengeData[8];
uint32 context[2];
tSmbStrHeader targetInfo;
uint8 buffer[1024];
uint32 bufIndex;
}tSmbNtlmAuthChallenge;
typedef struct
{
char ident[8];
uint32 msgType;
tSmbStrHeader lmResponse;
tSmbStrHeader ntResponse;
tSmbStrHeader uDomain;
tSmbStrHeader uUser;
tSmbStrHeader uWks;
tSmbStrHeader sessionKey;
uint32 flags;
uint8 buffer[1024];
uint32 bufIndex;
}tSmbNtlmAuthResponse;
/* public: */
#define SmbLength(ptr) (((ptr)->buffer - (uint8*)(ptr)) + (ptr)->bufIndex)
extern void dumpSmbNtlmAuthRequest(FILE *fp, tSmbNtlmAuthRequest *request);
extern void dumpSmbNtlmAuthChallenge(FILE *fp, tSmbNtlmAuthChallenge *challenge);
extern void dumpSmbNtlmAuthResponse(FILE *fp, tSmbNtlmAuthResponse *response);
extern void buildSmbNtlmAuthRequest(tSmbNtlmAuthRequest *request, char *user, char *domain);
extern void buildSmbNtlmAuthResponse(tSmbNtlmAuthChallenge *challenge, tSmbNtlmAuthResponse *response, char *user, char *password);
/* ntlm.h ends here */
">));
memset (opad, 0, sizeof (opad));
memcpy (ipad, password, pass_len);
memcpy (opad, password, pass_len);
for (i=0; i<64; i++) {
ipad[i] ^= 0x36;
opad[i] ^= 0x5c;
}
MD5Init (&ctx);
MD5Update (&ctx, ipad, sizeof (ipad));
MD5Update (&ctx, challenge, chal_len);
MD5Final (response, &ctx);
MD5Init (&ctx);
MD5Update (&ctx, opad, sizeof (opad));
MD5Update (&ctx, response, resp_len);
MD5Final (response, &ctx);
}
int do_cram_md5 (int sock, char *command, struct query *ctl, char *strip)
/* authenticate as per RFC2195 */
{
int result;
int len;
unsigned char buf1[1024];
unsigned char msg_id[768];
unsigned char response[16];
unsigned char reply[1024];
unsigned char *respdata;
gen_send (sock, "%s CRAM-MD5", command);
/* From RFC2195:
* The data encoded in the first ready response contains an
* presumptively arbitrary string of random digits, a timestamp, and the
* fully-qualified primary host name of the server. The syntax of the
* unencoded form must correspond to that of an RFC 822 'msg-id'
* [RFC822] as described in [POP3].
*/
if ((result = gen_recv (sock, buf1, sizeof (buf1)))) {
return result;
}
/* caller may specify a response prefix we should strip if present */
respdata = buf1;
if (strip && strncmp(buf1, strip, strlen(strip)) == 0)
respdata += strlen(strip);
len = from64tobits (msg_id, respdata, sizeof(msg_id));
if (len < 0) {
report (stderr, GT_("could not decode BASE64 challenge\n"));
return PS_AUTHFAIL;
} else if (len < sizeof (msg_id)) {
msg_id[len] = 0;
} else {
msg_id[sizeof (msg_id)-1] = 0;
}
if (outlevel >= O_DEBUG) {
report (stdout, GT_("decoded as %s\n"), msg_id);
}
/* The client makes note of the data and then responds with a string
* consisting of the user name, a space, and a 'digest'. The latter is
* computed by applying the keyed MD5 algorithm from [KEYED-MD5] where
* the key is a shared secret and the digested text is the timestamp
* (including angle-brackets).
*/
hmac_md5(ctl->password, strlen(ctl->password),
msg_id, strlen (msg_id),
response, sizeof (response));
snprintf (reply, sizeof(reply),
"%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
ctl->remotename,
response[0], response[1], response[2], response[3],
response[4], response[5], response[6], response[7],
response[8], response[9], response[10], response[11],
response[12], response[13], response[14], response[15]);
to64frombits (buf1, reply, strlen(reply));
/* ship the authentication back, accept the server's responses */
/* PMDF5.2 IMAP has a bug that requires this to be a single write */
suppress_tags = TRUE;
result = gen_transact(sock, buf1, sizeof(buf1));
suppress_tags = FALSE;
if (result)
return(result);
else
return(PS_SUCCESS);
}
/* cram.c ends here */
|