xref: /illumos-gate/usr/src/lib/gss_mechs/mech_krb5/mech/import_name.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
1 #pragma ident	"%Z%%M%	%I%	%E% SMI"
2 
3 /*
4  * Copyright 1993 by OpenVision Technologies, Inc.
5  *
6  * Permission to use, copy, modify, distribute, and sell this software
7  * and its documentation for any purpose is hereby granted without fee,
8  * provided that the above copyright notice appears in all copies and
9  * that both that copyright notice and this permission notice appear in
10  * supporting documentation, and that the name of OpenVision not be used
11  * in advertising or publicity pertaining to distribution of the software
12  * without specific, written prior permission. OpenVision makes no
13  * representations about the suitability of this software for any
14  * purpose.  It is provided "as is" without express or implied warranty.
15  *
16  * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18  * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
20  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22  * PERFORMANCE OF THIS SOFTWARE.
23  */
24 
25 /*
26  * $Id: import_name.c 18015 2006-05-17 05:26:12Z raeburn $
27  */
28 
29 #include "gssapiP_krb5.h"
30 
31 #ifndef NO_PASSWORD
32 #include <pwd.h>
33 #include <stdio.h>
34 #endif
35 
36 #ifdef HAVE_STRING_H
37 #include <string.h>
38 #else
39 #include <strings.h>
40 #endif
41 
42 /*
43  * errors:
44  * GSS_S_BAD_NAMETYPE	if the type is bogus
45  * GSS_S_BAD_NAME	if the type is good but the name is bogus
46  * GSS_S_FAILURE	if memory allocation fails
47  */
48 
49 OM_uint32
50 krb5_gss_import_name(minor_status, input_name_buffer,
51 		     input_name_type, output_name)
52      OM_uint32 *minor_status;
53      gss_buffer_t input_name_buffer;
54      gss_OID input_name_type;
55      gss_name_t *output_name;
56 {
57    krb5_context context;
58    krb5_principal princ;
59    krb5_error_code code;
60    char *stringrep, *tmp, *tmp2, *cp;
61    OM_uint32	length;
62 #ifndef NO_PASSWORD
63    struct passwd *pw;
64 #endif
65 
66    code = krb5_gss_init_context(&context);
67    if (code) {
68        *minor_status = code;
69        return GSS_S_FAILURE;
70    }
71 
72    /* set up default returns */
73 
74    *output_name = NULL;
75    *minor_status = 0;
76 
77    /* Go find the appropriate string rep to pass into parse_name */
78 
79    if ((input_name_type != GSS_C_NULL_OID) &&
80        (g_OID_equal(input_name_type, gss_nt_service_name) ||
81 	g_OID_equal(input_name_type, gss_nt_service_name_v2))) {
82       char *service, *host;
83 
84       if ((tmp =
85 	   (char *) xmalloc(input_name_buffer->length + 1)) == NULL) {
86 	 *minor_status = ENOMEM;
87 	 krb5_free_context(context);
88 	 return(GSS_S_FAILURE);
89       }
90 
91       memcpy(tmp, input_name_buffer->value, input_name_buffer->length);
92       tmp[input_name_buffer->length] = 0;
93 
94       service = tmp;
95       if ((host = strchr(tmp, '@'))) {
96 	 *host = '\0';
97 	 host++;
98       }
99 
100       code = krb5_sname_to_principal(context, host, service, KRB5_NT_SRV_HST,
101 				     &princ);
102 
103       xfree(tmp);
104    } else if ((input_name_type != GSS_C_NULL_OID) &&
105 	      (g_OID_equal(input_name_type, gss_nt_krb5_principal))) {
106       krb5_principal input;
107 
108       if (input_name_buffer->length != sizeof(krb5_principal)) {
109 	 *minor_status = (OM_uint32) G_WRONG_SIZE;
110 	 krb5_free_context(context);
111 	 return(GSS_S_BAD_NAME);
112       }
113 
114       input = *((krb5_principal *) input_name_buffer->value);
115 
116       if ((code = krb5_copy_principal(context, input, &princ))) {
117 	 *minor_status = code;
118 	 krb5_free_context(context);
119 	 return(GSS_S_FAILURE);
120       }
121    } else {
122 #ifndef NO_PASSWORD
123       uid_t uid;
124       struct passwd pwx;
125       char pwbuf[BUFSIZ];
126 #endif
127 
128       stringrep = NULL;
129 
130       if ((tmp =
131 	   (char *) xmalloc(input_name_buffer->length + 1)) == NULL) {
132 	 *minor_status = ENOMEM;
133 	 krb5_free_context(context);
134 	 return(GSS_S_FAILURE);
135       }
136       tmp2 = 0;
137 
138       memcpy(tmp, input_name_buffer->value, input_name_buffer->length);
139       tmp[input_name_buffer->length] = 0;
140 
141       if ((input_name_type == GSS_C_NULL_OID) ||
142 	  g_OID_equal(input_name_type, gss_nt_krb5_name) ||
143 	  g_OID_equal(input_name_type, gss_nt_user_name)) {
144 	 stringrep = (char *) tmp;
145 #ifndef NO_PASSWORD
146       } else if (g_OID_equal(input_name_type, gss_nt_machine_uid_name)) {
147 	 uid = *(uid_t *) input_name_buffer->value;
148       do_getpwuid:
149 	 if (k5_getpwuid_r(uid, &pwx, pwbuf, sizeof(pwbuf), &pw) == 0)
150 	     stringrep = pw->pw_name;
151 	 else
152 	    *minor_status = (OM_uint32) G_NOUSER;
153       } else if (g_OID_equal(input_name_type, gss_nt_string_uid_name)) {
154 	 uid = atoi(tmp);
155 	 goto do_getpwuid;
156 #endif
157       } else if (g_OID_equal(input_name_type, gss_nt_exported_name)) {
158 	 cp = tmp;
159 	 if (*cp++ != 0x04)
160 		 goto fail_name;
161 	 if (*cp++ != 0x01)
162 		 goto fail_name;
163 	 if (*cp++ != 0x00)
164 		 goto fail_name;
165 	 length = *cp++;
166 	 if (length != gss_mech_krb5->length+2)
167 		 goto fail_name;
168 	 if (*cp++ != 0x06)
169 		 goto fail_name;
170 	 length = *cp++;
171 	 if (length != gss_mech_krb5->length)
172 		 goto fail_name;
173 	 if (memcmp(cp, gss_mech_krb5->elements, length) != 0)
174 		 goto fail_name;
175 	 cp += length;
176 	 length = *cp++;
177 	 length = (length << 8) | *cp++;
178 	 length = (length << 8) | *cp++;
179 	 length = (length << 8) | *cp++;
180 	 tmp2 = malloc(length+1);
181 	 if (tmp2 == NULL) {
182 		 xfree(tmp);
183 		 *minor_status = ENOMEM;
184 		 krb5_free_context(context);
185 		 return GSS_S_FAILURE;
186 	 }
187 	 strncpy(tmp2, cp, length);
188 	 tmp2[length] = 0;
189 
190 	 stringrep = tmp2;
191      } else {
192 	 xfree(tmp);
193 	 krb5_free_context(context);
194 	 return(GSS_S_BAD_NAMETYPE);
195       }
196 
197       /* at this point, stringrep is set, or if not, *minor_status is. */
198 
199       if (stringrep)
200 	 code = krb5_parse_name(context, (char *) stringrep, &princ);
201       else {
202       fail_name:
203 	 xfree(tmp);
204 	 if (tmp2)
205 		 xfree(tmp2);
206 	 krb5_free_context(context);
207 	 return(GSS_S_BAD_NAME);
208       }
209 
210       if (tmp2)
211 	      xfree(tmp2);
212       xfree(tmp);
213    }
214 
215    /* at this point, a krb5 function has been called to set princ.  code
216       contains the return status */
217 
218    if (code) {
219       *minor_status = (OM_uint32) code;
220       krb5_free_context(context);
221       return(GSS_S_BAD_NAME);
222    }
223 
224    /* save the name in the validation database */
225 
226    if (! kg_save_name((gss_name_t) princ)) {
227       krb5_free_principal(context, princ);
228       krb5_free_context(context);
229       *minor_status = (OM_uint32) G_VALIDATE_FAILED;
230       return(GSS_S_FAILURE);
231    }
232 
233    krb5_free_context(context);
234 
235    /* return it */
236 
237    *output_name = (gss_name_t) princ;
238    return(GSS_S_COMPLETE);
239 }
240