summaryrefslogtreecommitdiff
path: root/imap/src/c-client/auth_ntl.c
blob: 0afe99fc4d9966239da1277545277a27263cb0e1 (plain)
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/* ========================================================================
 * Copyright 1988-2008 University of Washington
 * Copyright 2015      Imagination Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *
 * ========================================================================
 */

/*
 * Program:	NT LAN Manager authenticator
 *
 * Author:	Maciej W. Rozycki
 *
 * Date:	25 January 2015
 * Last Edited:	25 January 2015
 */

#include <ntlm.h>

long auth_ntlm_client (authchallenge_t challenger,authrespond_t responder,
			char *service,NETMBX *mb,void *stream,
			unsigned long *trial,char *user);

AUTHENTICATOR auth_ntl = {	/* secure, has full auth, hidden */
  AU_SECURE | AU_AUTHUSER | AU_HIDE,
  "NTLM",			/* authenticator name */
  NIL,				/* always valid */
  auth_ntlm_client,		/* client method */
  NIL,				/* no server method */
  NIL				/* next authenticator */
};

/* Client authenticator
 * Accepts: challenger function
 *	    responder function
 *	    SASL service name
 *	    parsed network mailbox structure
 *	    stream argument for functions
 *	    pointer to current trial count
 *	    returned user name
 * Returns: T if success, NIL otherwise, number of trials incremented if retry
 */

long auth_ntlm_client (authchallenge_t challenger, authrespond_t responder,
		       char *service, NETMBX *mb, void *stream,
		       unsigned long *trial, char *user)
{
  tSmbNtlmAuthChallenge *challenge;
  tSmbNtlmAuthResponse response;
  tSmbNtlmAuthRequest request;
  char tbuf[MAILTMPLEN];
  char ubuf[MAILTMPLEN];
  char pass[MAILTMPLEN];
  unsigned long clen;
  unsigned long ulen;
  unsigned long dlen;
  long ret = NIL;
  char *sep;

				/* get initial (empty) challenge */
  if (challenge = (*challenger) (stream, &clen)) {
    fs_give ((void **) &challenge);
    pass[0] = NIL;		/* prompt user */
    mm_login (mb, user, pass, *trial);
    if (!pass[0]) {		/* user requested abort */
      (*responder) (stream, NIL, 0);
      *trial = 0;		/* cancel subsequent attempts */
      ret = LONGT;		/* will get a BAD response back */
    } else {
				/* translate domain\user to user@domain */
				/* otherwise buildSmbNtlmAuthResponse */
				/* will override the domain requested with */
				/* one returned by the challenge message */
      sep = strchr (user, '\\');
      if (*sep) {
	dlen = sep - user;
	ulen = strlen (sep + 1);
	memcpy (ubuf, sep + 1, ulen);
	ubuf[ulen] = '@';
	memcpy (ubuf + ulen + 1, user, dlen);
	ubuf[ulen + dlen + 1] = '\0';
	user = ubuf;
      }
      buildSmbNtlmAuthRequest (&request, user, NULL);
				/* send a negotiate message */
      if ((*responder) (stream, (void *) &request, SmbLength (&request)) &&
	  (challenge = (*challenger) (stream, &clen))) {
				/* interpret the challenge message */
	buildSmbNtlmAuthResponse (challenge, &response, user, pass);
        fs_give ((void **) &challenge);
				/* send a response message */
	if ((*responder) (stream, (void *) &response, SmbLength (&response))) {
	  if (challenge = (*challenger) (stream, &clen))
	    fs_give ((void **) &challenge);
	  else {
	    ++*trial;		/* can try again if necessary */
	    ret = LONGT;	/* check the authentication */
	  }
	}
      }
    }
  }
  memset (pass,0,MAILTMPLEN);	/* erase password */
  if (!ret) *trial = 65535;	/* don't retry if bad protocol */
  return ret;
}