GSS_S_PROMPTING_NEEDED is a bit
[cyrus-sasl.git] / saslauthd / krbtf.c
1 /* MODULE: krbtf */
2 /* 
3  * Copyright (c) 2001 Carnegie Mellon University.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer. 
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *
17  * 3. The name "Carnegie Mellon University" must not be used to
18  *    endorse or promote products derived from this software without
19  *    prior written permission. For permission or any other legal
20  *    details, please contact  
21  *      Office of Technology Transfer
22  *      Carnegie Mellon University
23  *      5000 Forbes Avenue
24  *      Pittsburgh, PA  15213-3890
25  *      (412) 268-4387, fax: (412) 268-7395
26  *      tech-transfer@andrew.cmu.edu
27  *
28  * 4. Redistributions of any form whatsoever must retain the following
29  *    acknowledgment:
30  *    "This product includes software developed by Computing Services
31  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
32  *
33  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
34  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
35  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
36  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
37  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
38  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
39  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
40  */
41
42 /*
43  * Dec  4, 2002 by Dave Eckhardt <davide+receptionist@cs.cmu.edu>
44  * $Id: krbtf.c,v 1.2 2005/02/14 05:18:36 shadow Exp $
45  * This is inspired by code which was identical in both
46  * auth_krb4.c and auth_krb5.c.  This code is shared
47  * between the two implementations, contains protection
48  * against a race condition, and, when possible, uses
49  * Heimdal krb5's memory-only credential caches to avoid
50  * needless disk i/o.
51  */
52
53 #ifdef __GNUC__
54 #ident "$Id: krbtf.c,v 1.2 2005/02/14 05:18:36 shadow Exp $"
55 #endif
56
57 /* PUBLIC DEPENDENCIES */
58 #include <unistd.h>
59 #include <stdlib.h>
60 #include <errno.h>
61
62 #ifdef SASLAUTHD_THREADED /* is this really used??? */
63 #include <pthread.h>
64 #endif /* SASLAUTHD_THREADED */
65
66 #include "mechanisms.h"
67
68 #include <sys/types.h>
69 #include <sys/stat.h>
70 #include <string.h>
71 #include <syslog.h>
72
73 #ifdef AUTH_KRB4
74 #include <auth_krb4.h>
75 #define WANT_KRBTF
76 #endif /* WANT_KRBTF */
77
78 #ifdef AUTH_KRB5
79 #include <auth_krb5.h>
80 #define WANT_KRBTF
81 #endif /* WANT_KRBTF */
82
83 #ifdef WANT_KRBTF
84
85 /* PRIVATE DEPENDENCIES */
86 /* globals */
87
88 /* privates */
89 static char tf_dir[] = PATH_SASLAUTHD_RUNDIR "/.tf";
90 static char *tfn_cookie = 0;
91 static int tfn_cookie_len = 0;
92 static char pidstring[80];
93 int pidstring_len = 0;
94 /* END PRIVATE DEPENDENCIES */
95
96 #endif /* WANT_KRBTF */
97 \f
98 /* FUNCTION: krbtf_init */
99
100 /* SYNOPSIS
101  * Initialize the Kerberos IV/V ticket-file/credential-cache common code
102  *
103  * When possible, use Heimdal krb5's memory-only credential caches--
104  * this saves a whole bunch of useless disk i/o's to create and destroy
105  * a file which we don't want anybody to see anyway.
106  *
107  * If not, this function will create a private directory for ticket
108  * files and cache getpid() for later use.  Therefore, we must be
109  * called AFTER main() does whatever fork()ing it wants.
110  *
111  * END SYNOPSIS */
112
113 int                                     /* R: -1 on failure, else 0 */
114 krbtf_init (
115   /* PARAMETERS */
116   void                                  /* no parameters */
117   /* END PARAMETERS */
118   )
119 {
120 #ifdef WANT_KRBTF
121     /* VARIABLES */
122     int rc;                             /* return code holder */
123     struct stat sb;                     /* stat() work area */
124     /* END VARIABLES */
125     authmech_t *authmech;
126
127 #ifdef AUTH_KRB5
128     for (authmech = mechanisms; authmech->name != NULL; authmech++ ) {
129             if (authmech->initialize != auth_krb5_init) continue;
130             /* This execution is using krb5 */
131             /* Both MIT krb5 and Heimdal support MEMORY: ccaches */
132             tfn_cookie = "MEMORY:0";
133             tfn_cookie_len = strlen(tfn_cookie);
134             return 0;
135     }
136 #endif /* AUTH_KRB5 */
137
138     if (((rc = mkdir(tf_dir, 0700)) == 0) || (errno == EEXIST)) {
139         if ((rc = lstat(tf_dir, &sb)) == 0) {
140             if (sb.st_mode & S_IFLNK) {
141                 syslog(LOG_ERR, "krbtf_init: %s is a symbolic link", tf_dir);
142                 return -1;
143             }
144         }
145     }
146
147     if (rc != 0) {
148         syslog(LOG_ERR, "krbtf_init %s: %m", tf_dir);
149         return -1;
150     }
151
152     /* cache getpid() for use in filenames */
153     if ((pidstring_len = snprintf(pidstring, sizeof (pidstring), "%d", getpid())) >= sizeof (pidstring)) {
154             syslog(LOG_ERR, "krbtf_init pidstring too long(!?)");
155             return -1;
156     }
157
158     return 0;
159 #else /* WANT_KRBTF */
160         syslog(LOG_ERR, "krbtf_init: not compiled!");
161         return -1;
162 #endif /* WANT_KRBTF */
163 }
164
165 /* END FUNCTION: krbtf_init */
166 \f
167 /* FUNCTION: krbtf_name */
168
169 /* SYNOPSIS
170  * Spit a ticket-file/credentical-cache name into caller's array.
171  *
172  * If we can, emit the magic cookie for a memory-only krb5 ccname
173  * END SYNOPSIS */
174
175 int                                     /* R: -1 on failure, else 0 */
176 krbtf_name (
177   /* PARAMETERS */
178   char *tfname,                         /* O: where caller wants name */
179   int len                               /* I: available length */
180   /* END PARAMETERS */
181   )
182 {
183 #ifdef WANT_KRBTF
184     if (tfn_cookie_len) {
185         if (tfn_cookie_len + 1 > len) {
186             syslog(LOG_ERR, "krbtf_name: cookie name (%s) too long", tfn_cookie);
187             return -1;
188         }
189         strcpy(tfname, tfn_cookie);
190     } else {
191         int dir_len = sizeof (tf_dir) - 1; /* don't count the null */
192         int want_len = dir_len + 1 + pidstring_len + 1;
193
194         if (want_len > len) {
195             syslog(LOG_ERR, "krbtf_name: need room for %d bytes, got %d", want_len, len);
196             return -1;
197         }
198
199         strcpy(tfname, tf_dir);
200         tfname += dir_len; len -= dir_len;
201
202         *tfname++ = '/'; len--;
203
204         strcpy(tfname, pidstring);
205
206 #ifdef SASLAUTHD_THREADED /* is this really used??? */
207         tfname += pidstring_len;
208         len -= pidstring_len;
209
210         if (snprintf(tfname, len, "_%d", pthread_self() >= len)) {
211             syslog(LOG_ERR, "krbtf_name: no room for thread id");
212             return -1;
213         }
214 #endif /* SASLAUTHD_THREADED */
215     }
216
217     return 0;
218 #else /* WANT_KRBTF */
219         syslog(LOG_ERR, "krbtf_name: not compiled!");
220         return -1;
221 #endif /* WANT_KRBTF */
222 }
223 /* END FUNCTION: krbtf_name */
224
225 /* END MODULE: krbtf */