*** empty log message ***
[krb5.git] / src / lib / krb5 / os / hst_realm.c
1 /*
2  * $Source$
3  * $Author$
4  *
5  * Copyright 1990 by the Massachusetts Institute of Technology.
6  *
7  * For copying and distribution information, please see the file
8  * <krb5/copyright.h>.
9  *
10  * krb5_get_host_realm()
11  */
12
13 #if !defined(lint) && !defined(SABER)
14 static char rcsid_hst_realm_c[] =
15 "$Id$";
16 #endif  /* !lint & !SABER */
17
18 #include <krb5/copyright.h>
19
20 /*
21  Figures out the Kerberos realm names for host, filling in a
22  pointer to an argv[] style list of names, terminated with a null pointer.
23  
24  If host is NULL, the local host's realms are determined.
25
26  If there are no known realms for the host, the filled-in pointer is set
27  to NULL.
28
29  The pointer array and strings pointed to are all in allocated storage,
30  and should be freed by the caller when finished.
31
32  returns system errors
33 */
34
35 /*
36  * Implementation notes:
37  *
38  * this implementation only provides one realm per host, using the same
39  * mapping file used in kerberos v4.
40
41  * Given a fully-qualified domain-style primary host name,
42  * return the name of the Kerberos realm for the host.
43  * If the hostname contains no discernable domain, or an error occurs,
44  * return the local realm name, as supplied by krb5_get_default_realm().
45  * If the hostname contains a domain, but no translation is found,
46  * the hostname's domain is converted to upper-case and returned.
47  *
48  * The format of each line of the translation file is:
49  * domain_name kerberos_realm
50  * -or-
51  * host_name kerberos_realm
52  *
53  * domain_name should be of the form .XXX.YYY (e.g. .LCS.MIT.EDU)
54  * host names should be in the usual form (e.g. FOO.BAR.BAZ)
55  */
56
57
58 #include <krb5/krb5.h>
59 #include <krb5/krb5_err.h>
60 #include <krb5/ext-proto.h>
61 #include <stdio.h>
62 #include <krb5/libos-proto.h>
63 #include <errno.h>
64 #include <ctype.h>
65 #include <sys/param.h>
66
67 /* for old Unixes and friends ... */
68 #ifndef MAXHOSTNAMELEN
69 #define MAXHOSTNAMELEN 64
70 #endif
71
72 #define DEF_REALMNAME_SIZE      256
73
74 extern char *krb5_trans_file;
75
76 krb5_error_code
77 krb5_get_host_realm(host, realmsp)
78 const char *host;
79 char ***realmsp;
80 {
81     char **retrealms;
82     char *domain;
83     FILE *trans_file;
84     char trans_host[MAXHOSTNAMELEN+1];
85     char trans_realm[DEF_REALMNAME_SIZE];
86     krb5_error_code retval;
87     int scanval;
88     char scanstring[7+2*16];            /* 7 chars + 16 for each decimal
89                                            conversion */
90
91     if (!(retrealms = (char **)calloc(2, sizeof(*retrealms))))
92         return ENOMEM;
93     domain = index(host, '.');
94
95     /* prepare default */
96     if (domain) {
97         char *cp;
98
99         if (!(retrealms[0] = malloc(strlen(&domain[1])+1))) {
100             xfree(retrealms);
101             return ENOMEM;
102         }
103         strcpy(retrealms[0], &domain[1]);
104         /* Upper-case realm */
105         for (cp = retrealms[0]; *cp; cp++)
106             if (islower(*cp))
107                 *cp = toupper(*cp);
108     } else {
109         if (!(retrealms[0] = malloc(DEF_REALMNAME_SIZE))) {
110             xfree(retrealms);
111             return ENOMEM;
112         }
113         if (retval = krb5_get_default_realm(DEF_REALMNAME_SIZE-1,
114                                             retrealms[0])) {
115             xfree(retrealms[0]);
116             xfree(retrealms);
117             return retval;
118         }
119     }
120
121     if ((trans_file = fopen(krb5_trans_file, "r")) == (FILE *) 0) {
122         xfree(retrealms[0]);
123         xfree(retrealms);
124         return KRB5_TRANS_CANTOPEN;
125     }
126     (void) sprintf(scanstring, "%%%ds %%%ds",
127                    sizeof(trans_host)-1,sizeof(trans_realm)-1);
128     while (1) {
129         if ((scanval = fscanf(trans_file, scanstring,
130                               trans_host, trans_realm)) != 2) {
131             if (scanval == EOF) {
132                 fclose(trans_file);
133                 goto out;
134             }
135             continue;                   /* ignore broken lines */
136         }
137         trans_host[sizeof(trans_host)-1] = '\0';
138         trans_realm[sizeof(trans_realm)-1] = '\0';
139         if (!strcasecmp(trans_host, host)) {
140             /* exact match of hostname, so return the realm */
141             if (!(retrealms[0] = realloc(retrealms[0],
142                                          strlen(trans_realm)+1))) {
143                 xfree(retrealms);
144                 return ENOMEM;
145             }
146             (void) strcpy(retrealms[0], trans_realm);
147             fclose(trans_file);
148             goto out;
149         }
150         if ((trans_host[0] == '.') && domain) { 
151             /* this is a possible domain match */
152             if (!strcasecmp(trans_host, domain)) {
153                 /* domain match, save for later */
154                 if (!(retrealms[0] = realloc(retrealms[0],
155                                              strlen(trans_realm)+1))) {
156                     xfree(retrealms);
157                     return ENOMEM;
158                 }
159                 (void) strcpy(retrealms[0], trans_realm);
160                 continue;
161             }
162         }
163     }
164  out:
165     *realmsp = retrealms;
166     return 0;
167 }