1 /*
2
3 Copyright 1994, 1998 The Open Group
4
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of The Open Group shall
23 not be used in advertising or otherwise to promote the sale, use or
24 other dealings in this Software without prior written authorization
25 from The Open Group.
26
27 */
28
29 /*
30 * xdm - display manager daemon
31 * Author: Stephen Gildea, The Open Group
32 */
33
34 /*
35 * krb5auth
36 *
37 * generate Kerberos Version 5 authorization records
38 */
39
40 #include "dm.h"
41 #include "dm_error.h"
42
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <krb5/krb5.h>
46 #include <krb5/kdb.h> /* for TGTNAME */
47
48 /*ARGSUSED*/
49 void
Krb5InitAuth(unsigned short name_len,char * name)50 Krb5InitAuth (unsigned short name_len, char *name)
51 {
52 krb5_init_ets(); /* initialize error_message() tables */
53 }
54
55 /*
56 * Returns malloc'ed string that is the credentials cache name.
57 * name should be freed by caller.
58 */
59 char *
Krb5CCacheName(char * dname)60 Krb5CCacheName(char *dname)
61 {
62 char *name;
63 char *tmpdir;
64
65 tmpdir = getenv("TMPDIR");
66 if (!tmpdir)
67 tmpdir = "/tmp";
68 name = malloc(strlen(tmpdir) + strlen(dname) + 20);
69 if (!name)
70 return NULL;
71 sprintf(name, "FILE:%s/K5C", tmpdir);
72 CleanUpFileName(dname, name+strlen(name), strlen(dname)+1);
73 return name;
74 }
75
76 krb5_error_code
Krb5DisplayCCache(char * dname,krb5_ccache * ccache_return)77 Krb5DisplayCCache(char *dname, krb5_ccache *ccache_return)
78 {
79 krb5_error_code code;
80 char *name;
81
82 name = Krb5CCacheName(dname);
83 if (!name)
84 return ENOMEM;
85 Debug("resolving Kerberos cache %s\n", name);
86 code = krb5_cc_resolve(name, ccache_return);
87 free(name);
88 return code;
89 }
90
91 Xauth *
Krb5GetAuthFor(unsigned short namelen,char * name,char * dname)92 Krb5GetAuthFor(unsigned short namelen, char *name, char *dname)
93 {
94 Xauth *new;
95 char *filename;
96 struct stat statbuf;
97
98 new = malloc (sizeof *new);
99 if (!new)
100 return (Xauth *) 0;
101 new->family = FamilyWild;
102 new->address_length = 0;
103 new->address = 0;
104 new->number_length = 0;
105 new->number = 0;
106
107 if (dname)
108 {
109 filename = Krb5CCacheName(dname);
110 new->data = malloc (3 + strlen(filename) + 1);
111 if (!new->data)
112 {
113 free (filename);
114 free (new);
115 return (Xauth *) 0;
116 }
117 strcpy(new->data, "UU:");
118 strcat(new->data, filename);
119 free (filename);
120 new->data_length = strlen(new->data);
121 }
122 else
123 {
124 new->data = NULL;
125 new->data_length = 0;
126 }
127
128 new->name = malloc (namelen);
129 if (!new->name)
130 {
131 free (new->data);
132 free (new);
133 return (Xauth *) 0;
134 }
135 memmove( new->name, name, namelen);
136 new->name_length = namelen;
137 return new;
138 }
139
140 Xauth *
Krb5GetAuth(unsigned short namelen,char * name)141 Krb5GetAuth (unsigned short namelen, char *name)
142 {
143 return Krb5GetAuthFor(namelen, name, NULL);
144 }
145
146 int preauth_search_list[] = {
147 0,
148 KRB5_PADATA_ENC_TIMESTAMP,
149 -1
150 };
151
152 /*
153 * Krb5Init - lifted from kinit.c
154 * Get TGT.
155 * Returns 0 if successful, 1 if not.
156 */
157 int
Krb5Init(char * name,char * passwd,struct display * d)158 Krb5Init(
159 char *name,
160 char *passwd,
161 struct display *d) /* k5_ccache filled in if successful */
162 {
163 krb5_ccache ccache;
164 krb5_error_code code;
165 krb5_principal me;
166 krb5_creds my_creds;
167 krb5_principal server;
168 krb5_address **my_addresses;
169 krb5_timestamp now;
170 int i;
171
172 if (code = Krb5DisplayCCache(d->name, &ccache)) {
173 LogError("%s while getting Krb5 ccache for \"%s\"\n",
174 error_message(code), d->name);
175 return 1;
176 }
177
178 if (code = krb5_parse_name (name, &me)) {
179 LogError("%s while parsing Krb5 name \"%s\"\n",
180 error_message(code), name);
181 return 1;
182 }
183
184 code = krb5_cc_initialize (ccache, me);
185 if (code != 0) {
186 LogError("%s while initializing Krb5 cache \"%s\"\n",
187 error_message(code), krb5_cc_default_name());
188 return 1;
189 }
190
191 memset((char *)&my_creds, 0, sizeof(my_creds));
192
193 my_creds.client = me;
194
195 if (code = krb5_build_principal_ext(&server,
196 krb5_princ_realm(me)->length,
197 krb5_princ_realm(me)->data,
198 6, "krbtgt",
199 krb5_princ_realm(me)->length,
200 krb5_princ_realm(me)->data,
201 0)) {
202 LogError("%s while building Krb5 TGT server name\n",
203 error_message(code));
204 return 1;
205 }
206
207 my_creds.server = server;
208
209 code = krb5_os_localaddr(&my_addresses);
210 if (code != 0) {
211 LogError("%s while getting my address for Krb5\n",
212 error_message(code));
213 return 1;
214 }
215 if (code = krb5_timeofday(&now)) {
216 LogError("%s while getting time of day for Krb5\n",
217 error_message(code));
218 return 1;
219 }
220 my_creds.times.starttime = 0; /* start timer when request
221 gets to KDC */
222 my_creds.times.endtime = now + 60*60*8; /* 8 hours */
223 my_creds.times.renew_till = 0;
224
225 for (i = 0; preauth_search_list[i] >= 0; i++) {
226 code = krb5_get_in_tkt_with_password(0, my_addresses,
227 preauth_search_list[i],
228 ETYPE_DES_CBC_CRC,
229 KEYTYPE_DES,
230 passwd,
231 ccache,
232 &my_creds, 0);
233 if (code != KRB5KDC_PREAUTH_FAILED &&
234 code != KRB5KRB_ERR_GENERIC)
235 break;
236 }
237
238 krb5_free_principal(server);
239 krb5_free_addresses(my_addresses);
240
241 if (code) {
242 char *my_name = NULL;
243 int code2 = krb5_unparse_name(me, &my_name);
244 if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
245 LogError ("password incorrect for Krb5 principal \"%s\"\n",
246 code2 ? name : my_name);
247 }
248 else
249 LogError("%s while getting initial Krb5 credentials for \"%s\"\n",
250 error_message(code), code2 ? name : my_name);
251 free (my_name);
252 return 1;
253 }
254 krb5_cc_close(ccache);
255 return 0;
256 }
257