auth: Don't overflow hostName array
[openafs.git] / src / auth / writeconfig.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 #include <roken.h>
14 #include <afs/opr.h>
15
16 #include <afs/pthread_glock.h>
17 #include <afs/afsutil.h>
18 #include <rx/rxkad.h>
19
20 #include "cellconfig.h"
21 #include "keys.h"
22
23 /* write ThisCell and CellServDB containing exactly one cell's info specified
24     by acellInfo parm.   Useful only on the server (which describes only one cell).
25 */
26
27 static int
28 VerifyEntries(struct afsconf_cell *aci)
29 {
30     int i;
31     struct hostent *th;
32
33     for (i = 0; i < aci->numServers; i++) {
34         if (aci->hostAddr[i].sin_addr.s_addr == 0) {
35             /* no address spec'd */
36             if (*(aci->hostName[i]) != 0) {
37                 th = gethostbyname(aci->hostName[i]);
38                 if (!th) {
39                     printf("Host %s not found in host database...\n",
40                            aci->hostName[i]);
41                     return AFSCONF_FAILURE;
42                 }
43                 memcpy(&aci->hostAddr[i].sin_addr, th->h_addr,
44                        sizeof(afs_int32));
45             }
46             /* otherwise we're deleting this entry */
47         } else {
48             /* address spec'd, perhaps no name known */
49             if (aci->hostName[i][0] != 0)
50                 continue;       /* name known too */
51             /* figure out name, if possible */
52             th = gethostbyaddr((char *)(&aci->hostAddr[i].sin_addr), 4,
53                                AF_INET);
54             if (!th) {
55                 strcpy(aci->hostName[i], "UNKNOWNHOST");
56             } else {
57                 if (strlcpy(aci->hostName[i],
58                             th->h_name,
59                             sizeof(aci->hostName[i]))
60                         >= sizeof(aci->hostName[i])) {
61                    strcpy(aci->hostName[i], "UNKNOWNHOST");
62                 }
63             }
64         }
65     }
66     return 0;
67 }
68
69 /* Changed the interface to accept the afsconf_dir datastructure.
70    This is a handle to the internal cache that is maintained by the bosserver.
71    */
72
73 int
74 afsconf_SetCellInfo(struct afsconf_dir *adir, const char *apath,
75                     struct afsconf_cell *acellInfo)
76 {
77     afs_int32 code;
78
79     code = afsconf_SetExtendedCellInfo(adir, apath, acellInfo, NULL);
80     return code;
81 }
82
83 int
84 afsconf_SetExtendedCellInfo(struct afsconf_dir *adir,
85                             const char *apath,
86                             struct afsconf_cell *acellInfo, char clones[])
87 {
88     afs_int32 code;
89     int fd;
90     char tbuffer[1024];
91     FILE *tf;
92     afs_int32 i;
93
94     LOCK_GLOBAL_MUTEX;
95     /* write ThisCell file */
96     strcompose(tbuffer, 1024, apath, "/", AFSDIR_THISCELL_FILE, (char *)NULL);
97
98     fd = open(tbuffer, O_RDWR | O_CREAT | O_TRUNC, 0666);
99     if (fd < 0) {
100         UNLOCK_GLOBAL_MUTEX;
101         return errno;
102     }
103     i = (int)strlen(acellInfo->name);
104     code = write(fd, acellInfo->name, i);
105     if (code != i) {
106         UNLOCK_GLOBAL_MUTEX;
107         return AFSCONF_FAILURE;
108     }
109     if (close(fd) < 0) {
110         UNLOCK_GLOBAL_MUTEX;
111         return errno;
112     }
113
114     /* make sure we have both name and address for each host, looking up other
115      * if need be */
116     code = VerifyEntries(acellInfo);
117     if (code) {
118         UNLOCK_GLOBAL_MUTEX;
119         return code;
120     }
121
122     /* write CellServDB */
123     strcompose(tbuffer, 1024, apath, "/", AFSDIR_CELLSERVDB_FILE, (char *)NULL);
124     tf = fopen(tbuffer, "w");
125     if (!tf) {
126         UNLOCK_GLOBAL_MUTEX;
127         return AFSCONF_NOTFOUND;
128     }
129     fprintf(tf, ">%s    #Cell name\n", acellInfo->name);
130     for (i = 0; i < acellInfo->numServers; i++) {
131         code = acellInfo->hostAddr[i].sin_addr.s_addr;  /* net order */
132         if (code == 0)
133             continue;           /* delete request */
134         code = ntohl(code);     /* convert to host order */
135         if (clones && clones[i])
136             fprintf(tf, "[%d.%d.%d.%d]  #%s\n", (code >> 24) & 0xff,
137                     (code >> 16) & 0xff, (code >> 8) & 0xff, code & 0xff,
138                     acellInfo->hostName[i]);
139         else
140             fprintf(tf, "%d.%d.%d.%d    #%s\n", (code >> 24) & 0xff,
141                     (code >> 16) & 0xff, (code >> 8) & 0xff, code & 0xff,
142                     acellInfo->hostName[i]);
143     }
144     if (ferror(tf)) {
145         fclose(tf);
146         UNLOCK_GLOBAL_MUTEX;
147         return AFSCONF_FAILURE;
148     }
149     code = fclose(tf);
150
151     /* Reset the timestamp in the cache, so that
152      * the CellServDB is read into the cache next time.
153      * Resolves the lost update problem due to an inconsistent cache
154      */
155     if (adir)
156         adir->timeRead = 0;
157
158     UNLOCK_GLOBAL_MUTEX;
159     if (code == EOF)
160         return AFSCONF_FAILURE;
161     return 0;
162 }