Changed errno to SOCKET_ERRNO/SOCKET_SET_ERRNO for Mac OT SocketsLib
[krb5.git] / src / lib / krb5 / os / hst_realm.c
1 /*
2  * lib/krb5/os/hst_realm.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_host_realm()
25  */
26
27
28 /*
29  Figures out the Kerberos realm names for host, filling in a
30  pointer to an argv[] style list of names, terminated with a null pointer.
31  
32  If host is NULL, the local host's realms are determined.
33
34  If there are no known realms for the host, the filled-in pointer is set
35  to NULL.
36
37  The pointer array and strings pointed to are all in allocated storage,
38  and should be freed by the caller when finished.
39
40  returns system errors
41 */
42
43 /*
44  * Implementation notes:
45  *
46  * this implementation only provides one realm per host, using the same
47  * mapping file used in kerberos v4.
48
49  * Given a fully-qualified domain-style primary host name,
50  * return the name of the Kerberos realm for the host.
51  * If the hostname contains no discernable domain, or an error occurs,
52  * return the local realm name, as supplied by krb5_get_default_realm().
53  * If the hostname contains a domain, but no translation is found,
54  * the hostname's domain is converted to upper-case and returned.
55  *
56  * The format of each line of the translation file is:
57  * domain_name kerberos_realm
58  * -or-
59  * host_name kerberos_realm
60  *
61  * domain_name should be of the form .XXX.YYY (e.g. .LCS.MIT.EDU)
62  * host names should be in the usual form (e.g. FOO.BAR.BAZ)
63  */
64
65 #define NEED_SOCKETS
66 #include "k5-int.h"
67 #include <ctype.h>
68 #include <stdio.h>
69 #ifdef HAVE_STRING_H
70 #include <string.h>
71 #else
72 #include <strings.h>
73 #endif
74
75 /* for old Unixes and friends ... */
76 #ifndef MAXHOSTNAMELEN
77 #define MAXHOSTNAMELEN 64
78 #endif
79
80 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
81 krb5_get_host_realm(context, host, realmsp)
82     krb5_context context;
83     const char FAR *host;
84     char FAR * FAR * FAR *realmsp;
85 {
86     char **retrealms;
87     char *default_realm, *realm, *cp;
88     krb5_error_code retval;
89     int l;
90     char local_host[MAXHOSTNAMELEN+1];
91
92     if (host)
93         strncpy(local_host, host, MAXHOSTNAMELEN);
94     else {
95         if (gethostname(local_host, sizeof(local_host)-1) == -1)
96             return SOCKET_ERRNO;
97     }
98     local_host[sizeof(local_host)-1] = '\0';
99     for (cp = local_host; *cp; cp++) {
100         if (isupper(*cp))
101             *cp = tolower(*cp);
102     }
103     l = strlen(local_host);
104     /* strip off trailing dot */
105     if (l && local_host[l-1] == '.')
106             local_host[l-1] = 0;
107
108     /*
109        Search for the best match for the host or domain.
110        Example: Given a host a.b.c.d, try to match on:
111          1) A.B.C.D
112          2) .B.C.D
113          3) B.C.D
114          4) .C.D
115          5) C.D
116          6) .D
117          7) D
118      */
119
120     cp = local_host;
121     realm = default_realm = (char *)NULL;
122     while (cp) {
123         retval = profile_get_string(context->profile, "domain_realm", cp,
124                                     0, (char *)NULL, &realm);
125         if (retval)
126             return retval;
127         if (realm != (char *)NULL)
128             break;      /* Match found */
129
130         /* Setup for another test */
131         if (*cp == '.') {
132             cp++;
133             if (default_realm == (char *)NULL) {
134                 /* If nothing else works, use the host's domain */
135                 default_realm = cp;
136             }
137         } else {
138             cp = strchr(cp, '.');
139         }
140     }
141
142     if (realm == (char *)NULL) {
143             if (default_realm != (char *)NULL) {
144                     /* We are defaulting to the realm of the host */
145                     if (!(cp = (char *)malloc(strlen(default_realm)+1)))
146                             return ENOMEM;
147                     strcpy(cp, default_realm);
148                     realm = cp;
149
150                     /* Assume the realm name is upper case */
151                     for (cp = realm; *cp; cp++)
152                             if (islower(*cp))
153                                     *cp = toupper(*cp);
154             } else {
155                     /* We are defaulting to the local realm */
156                     retval = krb5_get_default_realm(context, &realm);
157                     if (retval) {
158                             return retval;
159                     }
160             }
161     }
162     if (!(retrealms = (char **)calloc(2, sizeof(*retrealms)))) {
163         if (realm != (char *)NULL)
164             free(realm);
165         return ENOMEM;
166     }
167
168     retrealms[0] = realm;
169     retrealms[1] = 0;
170     
171     *realmsp = retrealms;
172     return 0;
173 }