import_name.c revision 178826
186231Stmm/*
286231Stmm * Copyright (c) 1997 - 2003 Kungliga Tekniska H�gskolan
386231Stmm * (Royal Institute of Technology, Stockholm, Sweden).
486231Stmm * All rights reserved.
586231Stmm *
686231Stmm * Redistribution and use in source and binary forms, with or without
786231Stmm * modification, are permitted provided that the following conditions
886231Stmm * are met:
986231Stmm *
1086231Stmm * 1. Redistributions of source code must retain the above copyright
1186231Stmm *    notice, this list of conditions and the following disclaimer.
1286231Stmm *
1386231Stmm * 2. Redistributions in binary form must reproduce the above copyright
1486231Stmm *    notice, this list of conditions and the following disclaimer in the
1586231Stmm *    documentation and/or other materials provided with the distribution.
1686231Stmm *
1786231Stmm * 3. Neither the name of the Institute nor the names of its contributors
1886231Stmm *    may be used to endorse or promote products derived from this software
1986231Stmm *    without specific prior written permission.
2086231Stmm *
2186231Stmm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
2286231Stmm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2386231Stmm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2486231Stmm * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
2586231Stmm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2686231Stmm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2786231Stmm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2886231Stmm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2986231Stmm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3086231Stmm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3186231Stmm * SUCH DAMAGE.
3286231Stmm */
3386231Stmm
3486231Stmm#include "krb5/gsskrb5_locl.h"
3586231Stmm
3686231StmmRCSID("$Id: import_name.c 19031 2006-11-13 18:02:57Z lha $");
3786231Stmm
3886231Stmmstatic OM_uint32
3986231Stmmparse_krb5_name (OM_uint32 *minor_status,
4086231Stmm		 krb5_context context,
4186231Stmm		 const char *name,
4286231Stmm		 gss_name_t *output_name)
4386231Stmm{
4486231Stmm    krb5_principal princ;
4586231Stmm    krb5_error_code kerr;
4686231Stmm
4786231Stmm    kerr = krb5_parse_name (context, name, &princ);
4886231Stmm
4986231Stmm    if (kerr == 0) {
5086231Stmm	*output_name = (gss_name_t)princ;
5186231Stmm	return GSS_S_COMPLETE;
5286231Stmm    }
5386231Stmm    *minor_status = kerr;
5486231Stmm
5586231Stmm    if (kerr == KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED)
5686231Stmm	return GSS_S_BAD_NAME;
5786231Stmm
5886231Stmm    return GSS_S_FAILURE;
5986231Stmm}
6086231Stmm
6186231Stmmstatic OM_uint32
6286231Stmmimport_krb5_name (OM_uint32 *minor_status,
6386231Stmm		  krb5_context context,
6486231Stmm		  const gss_buffer_t input_name_buffer,
6586231Stmm		  gss_name_t *output_name)
6686231Stmm{
6786231Stmm    OM_uint32 ret;
6886231Stmm    char *tmp;
6986231Stmm
7086231Stmm    tmp = malloc (input_name_buffer->length + 1);
7186231Stmm    if (tmp == NULL) {
7286231Stmm	*minor_status = ENOMEM;
7386231Stmm	return GSS_S_FAILURE;
7486231Stmm    }
7586231Stmm    memcpy (tmp,
7686231Stmm	    input_name_buffer->value,
7786231Stmm	    input_name_buffer->length);
7886231Stmm    tmp[input_name_buffer->length] = '\0';
7986231Stmm
8086231Stmm    ret = parse_krb5_name(minor_status, context, tmp, output_name);
8186231Stmm    free(tmp);
8286231Stmm
8386231Stmm    return ret;
8486231Stmm}
8586231Stmm
8686231Stmmstatic OM_uint32
8786231Stmmimport_hostbased_name (OM_uint32 *minor_status,
8886231Stmm		       krb5_context context,
8986231Stmm		       const gss_buffer_t input_name_buffer,
9086231Stmm		       gss_name_t *output_name)
9186231Stmm{
9286231Stmm    krb5_error_code kerr;
93    char *tmp;
94    char *p;
95    char *host;
96    char local_hostname[MAXHOSTNAMELEN];
97    krb5_principal princ = NULL;
98
99    tmp = malloc (input_name_buffer->length + 1);
100    if (tmp == NULL) {
101	*minor_status = ENOMEM;
102	return GSS_S_FAILURE;
103    }
104    memcpy (tmp,
105	    input_name_buffer->value,
106	    input_name_buffer->length);
107    tmp[input_name_buffer->length] = '\0';
108
109    p = strchr (tmp, '@');
110    if (p != NULL) {
111	*p = '\0';
112	host = p + 1;
113    } else {
114	if (gethostname(local_hostname, sizeof(local_hostname)) < 0) {
115	    *minor_status = errno;
116	    free (tmp);
117	    return GSS_S_FAILURE;
118	}
119	host = local_hostname;
120    }
121
122    kerr = krb5_sname_to_principal (context,
123				    host,
124				    tmp,
125				    KRB5_NT_SRV_HST,
126				    &princ);
127    free (tmp);
128    *minor_status = kerr;
129    if (kerr == 0) {
130	*output_name = (gss_name_t)princ;
131	return GSS_S_COMPLETE;
132    }
133
134    if (kerr == KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED)
135	return GSS_S_BAD_NAME;
136
137    return GSS_S_FAILURE;
138}
139
140static OM_uint32
141import_export_name (OM_uint32 *minor_status,
142		    krb5_context context,
143		    const gss_buffer_t input_name_buffer,
144		    gss_name_t *output_name)
145{
146    unsigned char *p;
147    uint32_t length;
148    OM_uint32 ret;
149    char *name;
150
151    if (input_name_buffer->length < 10 + GSS_KRB5_MECHANISM->length)
152	return GSS_S_BAD_NAME;
153
154    /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */
155
156    p = input_name_buffer->value;
157
158    if (memcmp(&p[0], "\x04\x01\x00", 3) != 0 ||
159	p[3] != GSS_KRB5_MECHANISM->length + 2 ||
160	p[4] != 0x06 ||
161	p[5] != GSS_KRB5_MECHANISM->length ||
162	memcmp(&p[6], GSS_KRB5_MECHANISM->elements,
163	       GSS_KRB5_MECHANISM->length) != 0)
164	return GSS_S_BAD_NAME;
165
166    p += 6 + GSS_KRB5_MECHANISM->length;
167
168    length = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
169    p += 4;
170
171    if (length > input_name_buffer->length - 10 - GSS_KRB5_MECHANISM->length)
172	return GSS_S_BAD_NAME;
173
174    name = malloc(length + 1);
175    if (name == NULL) {
176	*minor_status = ENOMEM;
177	return GSS_S_FAILURE;
178    }
179    memcpy(name, p, length);
180    name[length] = '\0';
181
182    ret = parse_krb5_name(minor_status, context, name, output_name);
183    free(name);
184
185    return ret;
186}
187
188OM_uint32 _gsskrb5_import_name
189           (OM_uint32 * minor_status,
190            const gss_buffer_t input_name_buffer,
191            const gss_OID input_name_type,
192            gss_name_t * output_name
193           )
194{
195    krb5_context context;
196
197    *minor_status = 0;
198    *output_name = GSS_C_NO_NAME;
199
200    GSSAPI_KRB5_INIT (&context);
201
202    if (gss_oid_equal(input_name_type, GSS_C_NT_HOSTBASED_SERVICE) ||
203	gss_oid_equal(input_name_type, GSS_C_NT_HOSTBASED_SERVICE_X))
204	return import_hostbased_name (minor_status,
205				      context,
206				      input_name_buffer,
207				      output_name);
208    else if (gss_oid_equal(input_name_type, GSS_C_NO_OID)
209	     || gss_oid_equal(input_name_type, GSS_C_NT_USER_NAME)
210	     || gss_oid_equal(input_name_type, GSS_KRB5_NT_PRINCIPAL_NAME))
211 	/* default printable syntax */
212	return import_krb5_name (minor_status,
213				 context,
214				 input_name_buffer,
215				 output_name);
216    else if (gss_oid_equal(input_name_type, GSS_C_NT_EXPORT_NAME)) {
217	return import_export_name(minor_status,
218				  context,
219				  input_name_buffer,
220				  output_name);
221    } else {
222	*minor_status = 0;
223	return GSS_S_BAD_NAMETYPE;
224    }
225}
226