1 /* test-saslauthd.c: saslauthd test utility
5 * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
19 * 3. The name "Carnegie Mellon University" must not be used to
20 * endorse or promote products derived from this software without
21 * prior written permission. For permission or any other legal
22 * details, please contact
23 * Office of Technology Transfer
24 * Carnegie Mellon University
26 * Pittsburgh, PA 15213-3890
27 * (412) 268-4387, fax: (412) 268-7395
28 * tech-transfer@andrew.cmu.edu
30 * 4. Redistributions of any form whatsoever must retain the following
32 * "This product includes software developed by Computing Services
33 * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
35 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
36 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
37 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
38 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
39 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
40 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
41 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
44 #include <saslauthd.h>
48 #include <sys/types.h>
50 #include <sys/socket.h>
63 /* make utils.c happy */
64 int flags = LOG_USE_STDERR;
67 * Keep calling the read() system call with 'fd', 'buf', and 'nbyte'
68 * until all the data is read in or an error occurs.
70 int retry_read(int fd, void *inbuf, unsigned nbyte)
74 char *buf = (char *)inbuf;
76 if (nbyte == 0) return 0;
79 n = read(fd, buf, nbyte);
80 if (n == -1 || n == 0) {
81 if (errno == EINTR || errno == EAGAIN) continue;
87 if (n >= (int) nbyte) return nread;
94 /* saslauthd-authenticated login */
95 static int saslauthd_verify_password(const char *saslauthd_path,
99 const char *user_realm)
103 char *query_end = query;
105 struct sockaddr_un srvaddr;
107 unsigned short count;
109 char pwpath[sizeof(srvaddr.sun_path)];
110 const char *p = NULL;
115 if(!service) service = "imap";
116 if(!user_realm) user_realm = "";
117 if(!userid || !passwd) return -1;
119 if (saslauthd_path) {
120 strncpy(pwpath, saslauthd_path, sizeof(pwpath));
122 if (strlen(PATH_SASLAUTHD_RUNDIR) + 4 + 1 > sizeof(pwpath))
125 strcpy(pwpath, PATH_SASLAUTHD_RUNDIR);
126 strcat(pwpath, "/mux");
130 * build request of the form:
132 * count authid count password count service count realm
135 unsigned short u_len, p_len, s_len, r_len;
138 u_len = htons(strlen(userid));
139 p_len = htons(strlen(passwd));
140 s_len = htons(strlen(service));
141 r_len = htons((user_realm ? strlen(user_realm) : 0));
143 memcpy(query_end, &u_len, sizeof(unsigned short));
144 query_end += sizeof(unsigned short);
145 while (*userid) *query_end++ = *userid++;
147 memcpy(query_end, &p_len, sizeof(unsigned short));
148 query_end += sizeof(unsigned short);
149 while (*passwd) *query_end++ = *passwd++;
151 memcpy(query_end, &s_len, sizeof(unsigned short));
152 query_end += sizeof(unsigned short);
153 while (*service) *query_end++ = *service++;
155 memcpy(query_end, &r_len, sizeof(unsigned short));
156 query_end += sizeof(unsigned short);
157 if (user_realm) while (*user_realm) *query_end++ = *user_realm++;
161 s = open(pwpath, O_RDONLY);
167 arg.data_ptr = query;
168 arg.data_size = query_end - query;
172 arg.rsize = sizeof(response);
174 if(door_call(s, &arg) != 0) {
175 printf("NO \"door_call failed\"\n");
179 assert(arg.data_size < sizeof(response));
180 response[arg.data_size] = '\0';
184 s = socket(AF_UNIX, SOCK_STREAM, 0);
190 memset((char *)&srvaddr, 0, sizeof(srvaddr));
191 srvaddr.sun_family = AF_UNIX;
192 strncpy(srvaddr.sun_path, pwpath, sizeof(srvaddr.sun_path));
194 r = connect(s, (struct sockaddr *) &srvaddr, sizeof(srvaddr));
196 perror("connect() ");
203 iov[0].iov_len = query_end - query;
204 iov[0].iov_base = query;
206 if (retry_writev(s, iov, 1) == -1) {
207 fprintf(stderr,"write failed\n");
213 * read response of the form:
217 if (retry_read(s, &count, sizeof(count)) < (int) sizeof(count)) {
218 fprintf(stderr,"size read failed\n");
222 count = ntohs(count);
223 if (count < 2) { /* MUST have at least "OK" or "NO" */
225 fprintf(stderr,"bad response from saslauthd\n");
229 count = (int)sizeof(response) < count ? sizeof(response) : count;
230 if (retry_read(s, response, count) < count) {
232 fprintf(stderr,"read failed\n");
235 response[count] = '\0';
238 #endif /* USE_DOORS */
240 if (!strncmp(response, "OK", 2)) {
241 printf("OK \"Success.\"\n");
245 printf("NO \"authentication failed\"\n");
250 main(int argc, char *argv[])
252 const char *user = NULL, *password = NULL;
253 const char *realm = NULL, *service = NULL, *path = NULL;
256 unsigned passlen, verifylen;
257 const char *errstr = NULL;
259 char *user_domain = NULL;
262 while ((c = getopt(argc, argv, "p:u:r:s:f:R:")) != EOF)
265 repeat = atoi(optarg);
287 if (!user || !password)
291 (void)fprintf(stderr,
292 "%s: usage: %s -u username -p password\n"
293 " [-r realm] [-s servicename]\n"
294 " [-f socket path] [-R repeatnum]\n",
299 if (!repeat) repeat = 1;
300 for (c = 0; c < repeat; c++) {
301 /* saslauthd-authenticated login */
303 result = saslauthd_verify_password(path, user, password, service, realm);