Home | History | Annotate | Line # | Download | only in xdm
      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