1 
2 /*
3 ** Copyright 1998 - 2006 Double Precision, Inc.  See COPYING for
4 ** distribution information.
5 */
6 
7 #include	"courier_auth_config.h"
8 #include	"random128/random128.h"
9 #include	"courierauthsasl.h"
10 #include	<stdlib.h>
11 #include	<string.h>
12 #if	HAVE_UNISTD_H
13 #include	<unistd.h>
14 #endif
15 #include	<ctype.h>
16 #include	<stdio.h>
17 #include	<errno.h>
18 
19 extern char *strdupdefdomain(const char *userid, const char *s1,
20 			     const char *s2, const char *s3);
21 
authsasl_cram(const char * method,const char * initresponse,char * (* getresp)(const char *,void *),void * callback_arg,char ** authtype,char ** authdata)22 int authsasl_cram(const char *method, const char *initresponse,
23 		  char *(*getresp)(const char *, void *),
24 		  void *callback_arg,
25 		  char **authtype,
26 		  char **authdata)
27 {
28 const	char *randtoken;
29 char	hostnamebuf[256];
30 char	*challenge;
31 char	*challenge_base64;
32 char	*response;
33 char	*chrsp;
34 char	*q, *r, *s, *t;
35 int	plen;
36 
37 	if (initresponse && *initresponse)
38 	{
39 		if (write(2, "authsasl_cram: invalid request.\n", 32) < 0)
40 			; /* ignore gcc warning */
41 		return (AUTHSASL_ERROR);
42 	}
43 
44 	randtoken=random128();
45 	hostnamebuf[0]=0;
46 	if (gethostname(hostnamebuf, sizeof(hostnamebuf)-1))
47 		strcpy(hostnamebuf, "cram");
48 
49 	challenge=malloc(strlen(randtoken)+strlen(hostnamebuf)
50 			+sizeof("<@>"));
51 	if (!challenge)
52 	{
53 		perror("malloc");
54 		return (AUTHSASL_ERROR);
55 	}
56 	strcat(strcat(strcat(strcat(strcpy(challenge, "<"),
57 		randtoken), "@"), hostnamebuf), ">");
58 
59 	challenge_base64=authsasl_tobase64(challenge, -1);
60 	free(challenge);
61 	if (!challenge_base64)
62 	{
63 		perror("malloc");
64 		return (AUTHSASL_ERROR);
65 	}
66 
67 	response=getresp(challenge_base64, callback_arg);
68 	if (!response)
69 	{
70 		free(challenge_base64);
71 		return (AUTHSASL_ERROR);
72 	}
73 
74 	if (*response == '*')
75 	{
76 		free(challenge_base64);
77 		free(response);
78 		return (AUTHSASL_ABORTED);
79 	}
80 
81 	/* If DEFDOMAIN is set, pick apart the response and reassemble
82 	 * it, potentially with a default domain appended to the username */
83 	q=getenv("DEFDOMAIN");
84 	if (q && q[0])
85 	{
86 		r = 0;
87 		if (	(plen = authsasl_frombase64(response)) > 0 &&
88 			(response[plen]=0, (s = strchr(response, ' ')) != 0) &&
89 			(*s++ = 0, (t = strdupdefdomain(response, " ", s, "")) != 0) )
90 		{
91 			r = authsasl_tobase64(t, -1);
92 			free(t);
93 		}
94 		free(response);
95 		if ((response = r) == 0)
96 		{
97 			free(challenge_base64);
98 			return (AUTHSASL_ERROR);
99 		}
100 	}
101 
102 	chrsp=malloc(strlen(challenge_base64)+strlen(response)+3);
103 	if (!chrsp)
104 	{
105 		free(challenge_base64);
106 		free(response);
107 		perror("malloc");
108 		return (AUTHSASL_ERROR);
109 	}
110 
111 	strcat(strcat(strcat(strcpy(chrsp, challenge_base64), "\n"),
112 		response), "\n");
113 	free(challenge_base64);
114 	free(response);
115 
116 	if ( (*authtype=malloc(strlen(method)+1)) == 0)
117 	{
118 		free(chrsp);
119 		perror("malloc");
120 		return (AUTHSASL_ERROR);
121 	}
122 	strcpy( *authtype, method );
123 	*authdata=chrsp;
124 
125 	for (chrsp= *authtype; *chrsp; chrsp++)
126 		*chrsp= tolower( (int)(unsigned char)*chrsp );
127 
128 	return (AUTHSASL_OK);
129 }
130