Converted the krb5/krb directory to work under windows. Mostly added the
[krb5.git] / src / lib / krb5 / krb / conv_princ.c
1 /*
2  * lib/krb5/krb/conv_princ.c
3  *
4  * Copyright 1992 by the Massachusetts Institute of Technology.
5  * All Rights Reserved.
6  *
7  * Export of this software from the United States of America may
8  *   require a specific license from the United States Government.
9  *   It is the responsibility of any person or organization contemplating
10  *   export to obtain such a license before exporting.
11  * 
12  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13  * distribute this software and its documentation for any purpose and
14  * without fee is hereby granted, provided that the above copyright
15  * notice appear in all copies and that both that copyright notice and
16  * this permission notice appear in supporting documentation, and that
17  * the name of M.I.T. not be used in advertising or publicity pertaining
18  * to distribution of the software without specific, written prior
19  * permission.  M.I.T. makes no representations about the suitability of
20  * this software for any purpose.  It is provided "as is" without express
21  * or implied warranty.
22  * 
23  * Build a principal from a V4 specification, or separate a V5
24  * principal into name, instance, and realm.
25  * 
26  * NOTE: This is highly site specific, and is only really necessary
27  * for sites who need to convert from V4 to V5.  It is used by both
28  * the KDC and the kdb5_convert program.  Since its use is highly
29  * specialized, the necesary information is just going to be
30  * hard-coded in this file.
31  */
32
33 #include <krb5/krb5.h>
34 #include <string.h>
35 #include <ctype.h>
36
37 /* The maximum sizes for V4 aname, realm, sname, and instance +1 */
38 /* Taken from krb.h */
39 #define         ANAME_SZ        40
40 #define         REALM_SZ        40
41 #define         SNAME_SZ        40
42 #define         INST_SZ         40
43
44 struct krb_convert {
45         char    *v4_str;
46         char    *v5_str;
47         int     flags;
48 };
49
50 #define DO_REALM_CONVERSION 0x00000001
51
52 /*
53  * Kadmin doesn't do realm conversion because it's currently
54  * kadmin/REALM.NAME.  It should be kadmin/kerberos.master.host, but
55  * we'll fix that in the next release.
56  */
57 static struct krb_convert sconv_list[] = {
58     "kadmin",   "kadmin",       0,
59     "rcmd",     "host",         DO_REALM_CONVERSION,
60     "discuss",  "discuss",      DO_REALM_CONVERSION,
61     "rvdsrv",   "rvdsrv",       DO_REALM_CONVERSION,
62     "sample",   "sample",       DO_REALM_CONVERSION,
63     "olc",      "olc",          DO_REALM_CONVERSION,
64     "pop",      "pop",          DO_REALM_CONVERSION,
65     "sis",      "sis",          DO_REALM_CONVERSION,
66     "rfs",      "rfs",          DO_REALM_CONVERSION,
67     0,          0,
68 };
69
70 /*
71  * char *strnchr(s, c, n)
72  *   char *s;
73  *   char c;
74  *   int n;
75  *
76  * returns a pointer to the first occurrence of character c in the
77  * string s, or a NULL pointer if c does not occur in in the string;
78  * however, at most the first n characters will be considered.
79  *
80  * This falls in the "should have been in the ANSI C library"
81  * category. :-)
82  */
83 static char *strnchr(s, c, n)
84    register char *s, c;
85    register int n;
86 {
87      if (n < 1) 
88           return 0;
89      
90      while (n-- && *s) {
91           if (*s == c)
92                return s;
93           s++;
94      }
95      return 0;
96 }
97
98
99 /* XXX This calls for a new error code */
100 #define KRB5_INVALID_PRINCIPAL KRB5_LNAME_BADFORMAT
101
102 krb5_error_code INTERFACE
103 krb5_524_conv_principal(context, princ, name, inst, realm)
104     krb5_context context;
105     const krb5_principal princ;
106     char *name;
107     char *inst;
108     char *realm;
109 {
110      struct krb_convert *p;
111      krb5_data *comp;
112      char *c;
113
114      *name = *inst = '\0';
115      switch (krb5_princ_size(context, princ)) {
116      case 2:
117           /* Check if this principal is listed in the table */
118           comp = krb5_princ_component(context, princ, 0);
119           p = sconv_list;
120           while (p->v4_str) {
121                if (strncmp(p->v5_str, comp->data, comp->length) == 0) {
122                     /* It is, so set the new name now, and chop off */
123                     /* instance's domain name if requested */
124                     strcpy(name, p->v4_str);
125                     if (p->flags & DO_REALM_CONVERSION) {
126                          comp = krb5_princ_component(context, princ, 1);
127                          c = strnchr(comp->data, '.', comp->length);
128                          if (!c || (c - comp->data) > INST_SZ - 1)
129                               return KRB5_INVALID_PRINCIPAL;
130                          strncpy(inst, comp->data, c - comp->data);
131                          inst[c - comp->data] = '\0';
132                     }
133                     break;
134                }
135                p++;
136           }
137           /* If inst isn't set, the service isn't listed in the table, */
138           /* so just copy it. */
139           if (*inst == '\0') {
140                comp = krb5_princ_component(context, princ, 1);
141                if (comp->length >= INST_SZ - 1)
142                     return KRB5_INVALID_PRINCIPAL;
143                strncpy(inst, comp->data, comp->length);
144                inst[comp->length] = '\0';
145           }
146           /* fall through */
147      case 1:
148           /* name may have been set above; otherwise, just copy it */
149           if (*name == '\0') {
150                comp = krb5_princ_component(context, princ, 0);
151                if (comp->length >= ANAME_SZ)
152                     return KRB5_INVALID_PRINCIPAL;
153                strncpy(name, comp->data, comp->length);
154                name[comp->length] = '\0';
155           }
156           break;
157      default:
158           return KRB5_INVALID_PRINCIPAL;
159      }
160
161      comp = krb5_princ_realm(context, princ);
162      if (comp->length > REALM_SZ - 1)
163           return KRB5_INVALID_PRINCIPAL;
164      strncpy(realm, comp->data, comp->length);
165      realm[comp->length] = '\0';
166
167      return 0;
168 }
169
170 krb5_error_code INTERFACE
171 krb5_425_conv_principal(context, name, instance, realm, princ)
172    krb5_context context;
173    const char   *name;
174    const char   *instance;
175    const char   *realm;
176    krb5_principal       *princ;
177 {
178      struct krb_convert *p;
179      char buf[256];             /* V4 instances are limited to 40 characters */
180      krb5_error_code retval;
181      char *domain, *cp;
182      
183      if (instance) {
184           if (instance[0] == '\0') {
185                instance = 0;
186                goto not_service;
187           }
188           p = sconv_list;
189           while (1) {
190                if (!p->v4_str)
191                     goto not_service;
192                if (!strcmp(p->v4_str, name))
193                     break;
194                p++;
195           }
196           name = p->v5_str;
197           if (p->flags & DO_REALM_CONVERSION) {
198                strcpy(buf, instance);
199                retval = krb5_get_realm_domain(context, realm, &domain);
200                if (retval)
201                    return retval;
202                if (domain) {
203                    for (cp = domain; *cp; cp++)
204                        if (isupper(*cp))
205                            *cp = tolower(*cp);
206                    strcat(buf, domain);
207                    krb5_xfree(domain);
208                }
209                instance = buf;
210           }
211      }
212      
213 not_service:    
214      return(krb5_build_principal(context, princ, strlen(realm), realm, name,
215                                  instance, 0));
216 }