* locate_kdc.c (krb5_locate_kdc): Add parrentheses for assignment
[krb5.git] / src / lib / krb5 / os / locate_kdc.c
1 /*
2  * lib/krb5/os/locate_kdc.c
3  *
4  * Copyright 1990 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  * get socket addresses for KDC.
25  */
26
27 #define NEED_SOCKETS
28 #include "k5-int.h"
29 #include <stdio.h>
30
31 /*
32  * returns count of number of addresses found
33  */
34
35 krb5_error_code
36 krb5_locate_kdc(context, realm, addr_pp, naddrs)
37     krb5_context context;
38     const krb5_data *realm;
39     struct sockaddr **addr_pp;
40     int *naddrs;
41 {
42     const char  *realm_kdc_names[4];
43     char **hostlist, *host, *port, *cp;
44     krb5_error_code code;
45     int i, j, out, count;
46     struct sockaddr *addr_p;
47     struct sockaddr_in *sin_p;
48     struct hostent *hp;
49     struct servent *sp;
50 #ifdef KRB5_USE_INET
51     u_short udpport = htons(KRB5_DEFAULT_PORT);
52     u_short sec_udpport = htons(KRB5_DEFAULT_SEC_PORT);
53 #endif
54
55     if ((host = malloc(realm->length + 1)) == NULL) 
56         return ENOMEM;
57
58     strncpy(host, realm->data, realm->length);
59     host[realm->length] = '\0';
60     hostlist = 0;
61     
62     realm_kdc_names[0] = "realms";
63     realm_kdc_names[1] = host;
64     realm_kdc_names[2] = "kdc";
65     realm_kdc_names[3] = 0;
66
67     code = profile_get_values(context->profile, realm_kdc_names, &hostlist);
68     krb5_xfree(host);
69
70     if (code == PROF_NO_SECTION)
71         return KRB5_REALM_UNKNOWN;
72     if (code == PROF_NO_RELATION)
73         return KRB5_CONFIG_BADFORMAT;
74     if (code)
75         return code;
76
77 #ifdef KRB5_USE_INET
78     if ((sp = getservbyname(KDC_PORTNAME, "udp")))
79         udpport = sp->s_port;
80     if ((sp = getservbyname(KDC_SECONDARY_PORTNAME, "udp")))
81         sec_udpport = sp->s_port;
82 #endif
83     if (sec_udpport == udpport)
84         sec_udpport = 0;
85
86     count = 0;
87     while (hostlist && hostlist[count])
88             count++;
89     
90     if (count == 0) {
91         *naddrs = 0;
92         return 0;
93     }
94     
95 #ifdef KRB5_USE_INET
96     if (sec_udpport)
97             count = count * 2;
98 #endif
99
100     addr_p = (struct sockaddr *)malloc (sizeof (struct sockaddr) * count);
101
102     for (i=0, out=0; hostlist[i]; i++) {
103         host = hostlist[i];
104         /*
105          * Strip off excess whitespace
106          */
107         cp = strchr(host, ' ');
108         if (cp)
109             *cp = 0;
110         cp = strchr(host, '\t');
111         if (cp)
112             *cp = 0;
113         port = strchr(host, ':');
114         if (port) {
115             *port = 0;
116             port++;
117         }
118         hp = gethostbyname(hostlist[i]);
119         if (hp != 0) {
120             switch (hp->h_addrtype) {
121 #ifdef KRB5_USE_INET
122             case AF_INET:
123                 for (j=0; hp->h_addr_list[j]; j++) {
124                     sin_p = (struct sockaddr_in *) &addr_p[out++];
125                     memset ((char *)sin_p, 0, sizeof(struct sockaddr));
126                     sin_p->sin_family = hp->h_addrtype;
127                     sin_p->sin_port = port ? htons(atoi(port)) : udpport;
128                     memcpy((char *)&sin_p->sin_addr,
129                            (char *)hp->h_addr_list[j],
130                            sizeof(struct in_addr));
131                     if (out+1 >= count) {
132                         count += 5;
133                         addr_p = (struct sockaddr *)
134                             realloc ((char *)addr_p,
135                                      sizeof(struct sockaddr) * count);
136                     }
137                     if (sec_udpport && !port) {
138                         addr_p[out] = addr_p[out-1];
139                         sin_p = (struct sockaddr_in *) &addr_p[out++];
140                         sin_p->sin_port = sec_udpport;
141                     }
142                 }
143                 break;
144 #endif
145             default:
146                 break;
147             }
148         }
149         free(hostlist[i]);
150         hostlist[i] = 0;
151     }
152     free ((char *)hostlist);
153
154     if (out == 0) {     /* Couldn't resolve any KDC names */
155         free (addr_p);
156         return KRB5_REALM_CANT_RESOLVE;
157     }
158
159     *addr_pp = addr_p;
160     *naddrs = out;
161     return 0;
162 }