5b4c071a98262959e426b1ecfda3925beceb5b6f
[krb5.git] / src / lib / krb5 / os / realm_dom.c
1 /*
2  * lib/krb5/os/realm_dom.c
3  *
4  * Copyright 1990,1991 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  *
24  * krb5_get_realm_domain()
25  */
26
27
28 /*
29  * Determines the proper domain name for a realm.  This is mainly so that
30  * a krb4 principal can be converted properly into a krb5 principal.
31  * Currently, the same style of mapping file used in krb4.
32  *
33  * If realm is NULL, this function will assume the default realm
34  * of the local host.
35  *
36  * The returned domain is allocated, and must be freed by the caller.
37  *
38  * This was hacked together from krb5_get_host_realm().
39  */
40
41 #include "k5-int.h"
42 #include <ctype.h>
43 #include <stdio.h>
44
45 /* for old Unixes and friends ... */
46 #ifndef MAXHOSTNAMELEN
47 #define MAXHOSTNAMELEN 64
48 #endif
49
50 #define DEF_REALMNAME_SIZE      256
51
52 extern char *krb5_trans_file;
53
54 #ifdef _WINDOWS
55 /*
56  * Windows DLL can't use the fscanf routine. We need fscanf to read
57  * in the host and realm. Read_2str with read_1str duplicate the needed
58  * functionality. See also host_realm.c
59  */
60 static int
61 read_1str (FILE *fp, char *buf, int buflen) {
62     int c;
63
64     while (1) {
65         c = fgetc (fp);                         /* Past leading whitespace */
66         if (c == EOF)
67             return 0;
68         if (! isspace (c))
69             break;
70     }
71
72     while (1) {
73         if (buflen > 0) {                       /* Store the character */
74             *buf++ = (char) c;
75             --buflen;
76         }
77         if (buflen <= 0)                        /* Fscanf stops scanning... */
78             break;                              /* ...when buffer is full */
79
80         c = fgetc (fp);                         /* Get next character */
81         if (c == EOF || isspace (c))
82             break;
83     }
84
85     if (buflen)                                 /* Make ASCIIZ if room */
86         *buf = '\0';
87
88     return 1;
89 }
90
91 static int 
92 read_2str (FILE *fp, char *b1, int l1, char *b2, int l2) {
93     int n;
94
95     n = read_1str (fp, b1, l1);                 /* Read first string */
96     if (!n) return EOF;
97     n = read_1str (fp, b2, l2);                 /* Read second string */
98     if (!n) return 1;
99     return 2;
100 }
101
102 #endif /* _WINDOWS */
103
104 krb5_error_code INTERFACE
105 krb5_get_realm_domain(context, realm, domain)
106     krb5_context context;
107     const char *realm;
108     char **domain;
109 {
110     char **realmlist = NULL;
111     char *retdomain = NULL;
112     char trans_host[MAXHOSTNAMELEN+1];
113     char trans_realm[DEF_REALMNAME_SIZE];
114     krb5_error_code retval;
115     FILE *trans_file;
116     int scanval;
117     char scanstring[7+2*16];            /* 7 chars + 16 for each decimal
118                                            conversion */
119
120     if (realm == NULL) {
121         if (retval = krb5_get_host_realm(context, NULL, &realmlist))
122             return retval;
123         realm = realmlist[0];
124     }
125     krb5_find_config_files();
126     if ((trans_file = fopen(krb5_trans_file, "r")) == (FILE *) 0) {
127         if (realmlist != NULL) {
128             krb5_xfree(realmlist[0]);
129             krb5_xfree(realmlist);
130         }
131         return KRB5_TRANS_CANTOPEN;
132     }
133     (void) sprintf(scanstring, "%%%ds %%%ds",
134                    sizeof(trans_host)-1,sizeof(trans_realm)-1);
135     while (1) {
136 #ifdef _WINDOWS
137             scanval = read_2str (trans_file, trans_host, sizeof(trans_host)-1,
138                 trans_realm, sizeof(trans_realm)-1);
139 #else
140             scanval = fscanf(trans_file, scanstring, trans_host, trans_realm);
141 #endif
142         if (scanval != 2) {
143             if (scanval == EOF) {
144                 fclose(trans_file);
145                 if (realmlist != NULL) {
146                     krb5_xfree(realmlist[0]);
147                     krb5_xfree(realmlist);
148                 }
149                 if ((retdomain = malloc(strlen(realm) + 2)) == NULL)
150                     return ENOMEM;
151                 strcpy(retdomain, ".");
152                 strcat(retdomain, realm); /* return the realm as the domain
153                                              if lookup fails */
154                 *domain = retdomain;
155                 return 0;
156             }
157             continue;
158         }
159         trans_host[sizeof(trans_host)-1] = '\0';
160         trans_realm[sizeof(trans_realm)-1] = '\0';
161         if (!strcmp(trans_realm, realm)) {
162             if (trans_host[0] == '.') {
163                 if ((retdomain = malloc(strlen(trans_host) + 1)) == NULL) {
164                     if (realmlist != NULL) {
165                         krb5_xfree(realmlist[0]);
166                         krb5_xfree(realmlist);
167                     }
168                     return ENOMEM;
169                 }
170                 (void)strcpy(retdomain, trans_host);
171                 fclose(trans_file);
172                 if (realmlist != NULL) {
173                     krb5_xfree(realmlist[0]);
174                     krb5_xfree(realmlist);
175                 }
176                 *domain = retdomain;
177                 return 0;
178             } else
179                 continue;
180         }
181     }
182 }