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 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 * 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 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 * 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 memcpy(new->name, name, namelen); 136 new->name_length = namelen; 137 return new; 138 } 139 140 Xauth * 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 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