Changed errno to SOCKET_ERRNO/SOCKET_SET_ERRNO for Mac OT SocketsLib
[krb5.git] / src / lib / krb5 / os / sn2princ.c
1 /*
2  * lib/krb5/os/sn2princ.c
3  *
4  * Copyright 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  * Convert a hostname and service name to a principal in the "standard"
25  * form.
26  */
27
28 #define NEED_SOCKETS
29 #include "k5-int.h"
30 #include <ctype.h>
31 #ifdef HAVE_SYS_PARAM_H
32 #include <sys/param.h>
33 #endif
34
35 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
36 krb5_sname_to_principal(context, hostname, sname, type, ret_princ)
37     krb5_context context;
38     const char FAR * hostname;
39     const char FAR * sname;
40     krb5_int32 type;
41     krb5_principal FAR * ret_princ;
42 {
43     struct hostent *hp;
44     char **hrealms, *realm, *remote_host;
45     krb5_error_code retval;
46     register char *cp;
47     char localname[MAXHOSTNAMELEN];
48
49
50     if ((type == KRB5_NT_UNKNOWN) ||
51         (type == KRB5_NT_SRV_HST)) {
52
53         /* if hostname is NULL, use local hostname */
54         if (! hostname) {
55             if (gethostname(localname, MAXHOSTNAMELEN))
56                 return SOCKET_ERRNO;
57             hostname = localname;
58         }
59
60         /* if sname is NULL, use "host" */
61         if (! sname)
62             sname = "host";
63
64         /* copy the hostname into non-volatile storage */
65
66         if (type == KRB5_NT_SRV_HST) {
67             char *addr;
68             
69             if (!(hp = gethostbyname(hostname)))
70                 return KRB5_ERR_BAD_HOSTNAME;
71             remote_host = strdup(hp->h_name);
72             if (!remote_host)
73                 return ENOMEM;
74             /*
75              * Do a reverse resolution to get the full name, just in
76              * case there's some funny business going on.  If there
77              * isn't an in-addr record, give up.
78              */
79             addr = malloc(hp->h_length);
80             if (!addr)
81                 return ENOMEM;
82             memcpy(addr, hp->h_addr, hp->h_length);
83             hp = gethostbyaddr(addr, hp->h_length, hp->h_addrtype);
84             free(addr);
85             if (hp) {
86                 free(remote_host);
87                 remote_host = strdup(hp->h_name);
88                 if (!remote_host)
89                     return ENOMEM;
90             }
91         } else /* type == KRB5_NT_UNKNOWN */ {
92             remote_host = strdup((char *) hostname);
93         }
94         if (!remote_host)
95             return ENOMEM;
96
97         if (type == KRB5_NT_SRV_HST)
98             for (cp = remote_host; *cp; cp++)
99                 if (isupper(*cp))
100                     *cp = tolower(*cp);
101
102         /*
103          * Windows NT5's broken resolver gratuitously tacks on a
104          * trailing period to the hostname (at least it does in
105          * Beta2).  Find and remove it.
106          */
107         if (remote_host[0]) {
108                 cp = remote_host + strlen(remote_host)-1;
109                 if (*cp == '.')
110                         *cp = 0;
111         }
112         
113
114         if (retval = krb5_get_host_realm(context, remote_host, &hrealms)) {
115             free(remote_host);
116             return retval;
117         }
118         if (!hrealms[0]) {
119             free(remote_host);
120             krb5_xfree(hrealms);
121             return KRB5_ERR_HOST_REALM_UNKNOWN;
122         }
123         realm = hrealms[0];
124
125         retval = krb5_build_principal(context, ret_princ, strlen(realm),
126                                       realm, sname, remote_host,
127                                       (char *)0);
128
129         krb5_princ_type(context, *ret_princ) = type;
130
131         free(remote_host);
132
133         krb5_free_host_realm(context, hrealms);
134         return retval;
135     } else {
136         return KRB5_SNAME_UNSUPP_NAMETYPE;
137     }
138 }
139