1 /*
2  * lib/krb5/krb/bld_princ.c
3  *
4  * Copyright 1991 by the Massachusetts Institute of Technology.
5  * All Rights Reserved.
6  *
7  * Copyright 2020 Nexenta by DDN, Inc. All rights reserved.
8  *
9  * Export of this software from the United States of America may
10  *   require a specific license from the United States Government.
11  *   It is the responsibility of any person or organization contemplating
12  *   export to obtain such a license before exporting.
13  *
14  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
15  * distribute this software and its documentation for any purpose and
16  * without fee is hereby granted, provided that the above copyright
17  * notice appear in all copies and that both that copyright notice and
18  * this permission notice appear in supporting documentation, and that
19  * the name of M.I.T. not be used in advertising or publicity pertaining
20  * to distribution of the software without specific, written prior
21  * permission.  Furthermore if you modify this software you must label
22  * your software as modified software and not distribute it in such a
23  * fashion that it might be confused with the original M.I.T. software.
24  * M.I.T. makes no representations about the suitability of
25  * this software for any purpose.  It is provided "as is" without express
26  * or implied warranty.
27  *
28  *
29  * Build a principal from a list of strings
30  */
31 
32 #include <stdarg.h>
33 #include "k5-int.h"
34 
35 /*ARGSUSED*/
36 krb5_error_code
37 KRB5_CALLCONV
krb5_build_principal_va(krb5_context context,krb5_principal princ,unsigned int rlen,const char * realm,va_list ap)38 krb5_build_principal_va(krb5_context context, krb5_principal princ, unsigned int rlen, const char *realm, va_list ap)
39 {
40     register int i, count = 0;
41     register char *next;
42     char *tmpdata;
43     krb5_data *data;
44 
45     /* guess at an initial sufficent count of 2 pieces */
46     count = 2;
47 
48     /* get space for array and realm, and insert realm */
49     data = (krb5_data *) malloc(sizeof(krb5_data) * count);
50     if (data == 0)
51 	return ENOMEM;
52     krb5_princ_set_realm_length(context, princ, rlen);
53     tmpdata = malloc(rlen + 1);
54     if (!tmpdata) {
55 	free (data);
56 	return ENOMEM;
57     }
58     krb5_princ_set_realm_data(context, princ, tmpdata);
59     memcpy(tmpdata, realm, rlen);
60     tmpdata[rlen] = '\0';
61 
62     /* process rest of components */
63 
64     for (i = 0, next = va_arg(ap, char *);
65 	 next;
66 	 next = va_arg(ap, char *), i++) {
67 	if (i == count) {
68 	    /* not big enough.  realloc the array */
69 	    krb5_data *p_tmp;
70 	    p_tmp = (krb5_data *) realloc((char *)data,
71 					  sizeof(krb5_data)*(count*2));
72 	    if (!p_tmp) {
73 	    free_out:
74 		    while (--i >= 0)
75 			krb5_xfree(data[i].data);
76 		    krb5_xfree(data);
77 		    krb5_xfree(tmpdata);
78 		    return (ENOMEM);
79 	    }
80 	    count *= 2;
81 	    data = p_tmp;
82 	}
83 
84 	data[i].length = strlen(next);
85 	data[i].data = strdup(next);
86 	if (!data[i].data)
87 	    goto free_out;
88     }
89     princ->data = data;
90     princ->length = i;
91     princ->type = KRB5_NT_UNKNOWN;
92     princ->magic = KV5M_PRINCIPAL;
93     return 0;
94 }
95 
96 krb5_error_code KRB5_CALLCONV_C
krb5_build_principal(krb5_context context,krb5_principal * princ,unsigned int rlen,const char * realm,...)97 krb5_build_principal(krb5_context context,  krb5_principal * princ,
98 		     unsigned int rlen,
99 		     const char * realm, ...)
100 {
101     va_list ap;
102     krb5_error_code retval;
103     krb5_principal pr_ret = (krb5_principal)malloc(sizeof(krb5_principal_data));
104 
105     if (!pr_ret)
106 	return ENOMEM;
107 
108     va_start(ap, realm);
109     retval = krb5_build_principal_va(context, pr_ret, rlen, realm, ap);
110     va_end(ap);
111     if (retval == 0)
112 	*princ = pr_ret;
113     return retval;
114 }
115