1 /*
2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * lib/krb5/krb/copy_princ.c
8  *
9  * Copyright 1990 by the Massachusetts Institute of Technology.
10  * All Rights Reserved.
11  *
12  * Export of this software from the United States of America may
13  *   require a specific license from the United States Government.
14  *   It is the responsibility of any person or organization contemplating
15  *   export to obtain such a license before exporting.
16  *
17  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
18  * distribute this software and its documentation for any purpose and
19  * without fee is hereby granted, provided that the above copyright
20  * notice appear in all copies and that both that copyright notice and
21  * this permission notice appear in supporting documentation, and that
22  * the name of M.I.T. not be used in advertising or publicity pertaining
23  * to distribution of the software without specific, written prior
24  * permission.  Furthermore if you modify this software you must label
25  * your software as modified software and not distribute it in such a
26  * fashion that it might be confused with the original M.I.T. software.
27  * M.I.T. makes no representations about the suitability of
28  * this software for any purpose.  It is provided "as is" without express
29  * or implied warranty.
30  *
31  *
32  * krb5_copy_principal()
33  */
34 
35 #include "k5-int.h"
36 
37 /*
38  * Copy a principal structure, with fresh allocation.
39  */
40 /*ARGSUSED*/
41 krb5_error_code KRB5_CALLCONV
krb5_copy_principal(krb5_context context,krb5_const_principal inprinc,krb5_principal * outprinc)42 krb5_copy_principal(krb5_context context, krb5_const_principal inprinc, krb5_principal *outprinc)
43 {
44     register krb5_principal tempprinc;
45     register int i, nelems;
46 
47     tempprinc = (krb5_principal)MALLOC(sizeof(krb5_principal_data));
48 
49     if (tempprinc == 0)
50 	return ENOMEM;
51 
52     *tempprinc = *inprinc;
53 
54     nelems = (int) krb5_princ_size(context, inprinc);
55     tempprinc->data = MALLOC(nelems * sizeof(krb5_data));
56 
57     if (tempprinc->data == 0) {
58 	FREE((char *)tempprinc, sizeof(krb5_principal_data));
59 	return ENOMEM;
60     }
61 
62     for (i = 0; i < nelems; i++) {
63 	unsigned int len = krb5_princ_component(context, inprinc, i)->length;
64 	krb5_princ_component(context, tempprinc, i)->length = len;
65 
66         /*
67          * Allocate one extra byte for trailing zero byte so string ops
68          * can be used on the components.
69          */
70 	if (len &&
71             ((krb5_princ_component(context, tempprinc, i)->data =
72 	      MALLOC(len + 1)) == 0)) {
73 	    while (--i >= 0)
74 		FREE(krb5_princ_component(context, tempprinc, i)->data,
75 			krb5_princ_component(context, inprinc, i)->length + 1);
76 	    FREE (tempprinc->data, nelems * sizeof(krb5_data));
77 	    FREE (tempprinc,sizeof(krb5_principal_data));
78 	    return ENOMEM;
79 	}
80 	if (len)
81 	    (void) memcpy(krb5_princ_component(context, tempprinc, i)->data,
82 		   krb5_princ_component(context, inprinc, i)->data, len);
83 	else
84 	    krb5_princ_component(context, tempprinc, i)->data = 0;
85     }
86 
87     tempprinc->realm.length = inprinc->realm.length;
88 
89     /*
90      * Allocate one extra byte for the realm name string terminator. The
91      * realm and principle component strings alway leave a null byte after
92      * 'length' bytes that needs to be malloc/freed.
93      */
94     tempprinc->realm.data = MALLOC(tempprinc->realm.length + 1);
95     if (!tempprinc->realm.data) {
96         for (i = 0; i < nelems; i++)
97 	    FREE(krb5_princ_component(context, tempprinc, i)->data,
98                 krb5_princ_component(context, inprinc, i)->length + 1);
99         FREE(tempprinc->data, nelems * sizeof(krb5_data));
100         FREE(tempprinc, sizeof(krb5_principal_data));
101 	return ENOMEM;
102     }
103     memcpy(tempprinc->realm.data, inprinc->realm.data,
104 	   inprinc->realm.length);
105     tempprinc->realm.data[tempprinc->realm.length] = 0;
106 
107     *outprinc = tempprinc;
108     return 0;
109 }
110