File: authsaslcram.c

package info (click to toggle)
courier-authlib 0.72.4-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 14,824 kB
  • sloc: ansic: 15,828; sh: 5,047; cpp: 4,205; makefile: 853; perl: 761
file content (129 lines) | stat: -rw-r--r-- 2,790 bytes parent folder | download | duplicates (7)
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

/*
** Copyright 1998 - 2006 Double Precision, Inc.  See COPYING for
** distribution information.
*/

#include	"courier_auth_config.h"
#include	"random128/random128.h"
#include	"courierauthsasl.h"
#include	<stdlib.h>
#include	<string.h>
#if	HAVE_UNISTD_H
#include	<unistd.h>
#endif
#include	<ctype.h>
#include	<stdio.h>
#include	<errno.h>

extern char *strdupdefdomain(const char *userid, const char *s1,
			     const char *s2, const char *s3);

int authsasl_cram(const char *method, const char *initresponse,
		  char *(*getresp)(const char *, void *),
		  void *callback_arg,
		  char **authtype,
		  char **authdata)
{
const	char *randtoken;
char	hostnamebuf[256];
char	*challenge;
char	*challenge_base64;
char	*response;
char	*chrsp;
char	*q, *r, *s, *t;
int	plen;

	if (initresponse && *initresponse)
	{
		if (write(2, "authsasl_cram: invalid request.\n", 32) < 0)
			; /* ignore gcc warning */
		return (AUTHSASL_ERROR);
	}

	randtoken=random128();
	hostnamebuf[0]=0;
	if (gethostname(hostnamebuf, sizeof(hostnamebuf)-1))
		strcpy(hostnamebuf, "cram");

	challenge=malloc(strlen(randtoken)+strlen(hostnamebuf)
			+sizeof("<@>"));
	if (!challenge)
	{
		perror("malloc");
		return (AUTHSASL_ERROR);
	}
	strcat(strcat(strcat(strcat(strcpy(challenge, "<"),
		randtoken), "@"), hostnamebuf), ">");

	challenge_base64=authsasl_tobase64(challenge, -1);
	free(challenge);
	if (!challenge_base64)
	{
		perror("malloc");
		return (AUTHSASL_ERROR);
	}

	response=getresp(challenge_base64, callback_arg);
	if (!response)
	{
		free(challenge_base64);
		return (AUTHSASL_ERROR);
	}

	if (*response == '*')
	{
		free(challenge_base64);
		free(response);
		return (AUTHSASL_ABORTED);
	}

	/* If DEFDOMAIN is set, pick apart the response and reassemble
	 * it, potentially with a default domain appended to the username */
	q=getenv("DEFDOMAIN");
	if (q && q[0])
	{
		r = 0;
		if (	(plen = authsasl_frombase64(response)) > 0 &&
			(response[plen]=0, (s = strchr(response, ' ')) != 0) &&
			(*s++ = 0, (t = strdupdefdomain(response, " ", s, "")) != 0) )
		{
			r = authsasl_tobase64(t, -1);
			free(t);
		}
		free(response);
		if ((response = r) == 0)
		{
			free(challenge_base64);
			return (AUTHSASL_ERROR);
		}
	}

	chrsp=malloc(strlen(challenge_base64)+strlen(response)+3);
	if (!chrsp)    
	{
		free(challenge_base64);
		free(response);
		perror("malloc");
		return (AUTHSASL_ERROR);
	}

	strcat(strcat(strcat(strcpy(chrsp, challenge_base64), "\n"),
		response), "\n");
	free(challenge_base64);
	free(response);

	if ( (*authtype=malloc(strlen(method)+1)) == 0)
	{
		free(chrsp);
		perror("malloc");
		return (AUTHSASL_ERROR);
	}
	strcpy( *authtype, method );
	*authdata=chrsp;

	for (chrsp= *authtype; *chrsp; chrsp++)
		*chrsp= tolower( (int)(unsigned char)*chrsp );

	return (AUTHSASL_OK);
}