1 /* $OpenBSD: mkalias.c,v 1.6 2001/02/05 14:47:17 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Mats O Jansson <moj@stacken.kth.se> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Mats O Jansson 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 22 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef LINT 35 static char rcsid[] = "$OpenBSD: mkalias.c,v 1.6 2001/02/05 14:47:17 deraadt Exp $"; 36 #endif 37 38 #include <ctype.h> 39 #include <fcntl.h> 40 #include <netdb.h> 41 #include <stdio.h> 42 #include <string.h> 43 #include <unistd.h> 44 #include <sys/param.h> 45 #include <sys/types.h> 46 #include <netinet/in.h> 47 #include <arpa/nameser.h> 48 #include <resolv.h> 49 #include "ypdb.h" 50 #include "ypdef.h" 51 52 extern char *__progname; /* from crt0.o */ 53 54 void 55 split_address(address, len, user, host) 56 char *address; 57 int len; 58 char *user, *host; 59 { 60 char *c,*s,*r; 61 int i = 0; 62 63 if (index(address,'@')) { 64 65 s = user; 66 67 for(c = address; i < len; i++) { 68 if (*c == '@') { 69 *s = '\0'; 70 s = host; 71 } else { 72 *s++ = *c; 73 } 74 c++; 75 } 76 *s = '\0'; 77 78 } 79 80 if (r = rindex(address,'!')) { 81 82 s = host; 83 84 for(c = address; i < len; i++) { 85 if (c == r) { 86 *s = '\0'; 87 s = user; 88 } else { 89 *s++ = *c; 90 } 91 c++; 92 } 93 *s = '\0'; 94 95 } 96 97 } 98 99 int 100 check_host(address, host, dflag, uflag, Eflag) 101 char *address, *host; 102 int dflag, uflag, Eflag; 103 { 104 char answer[PACKETSZ]; 105 int status; 106 107 if ((dflag && index(address,'@')) || 108 (uflag && index(address,'!'))) return(0); 109 110 if ((_res.options & RES_INIT) == 0) 111 res_init(); 112 113 status = res_search(host, C_IN, T_AAAA, answer, sizeof(answer)); 114 115 if (status == -1) 116 status = res_search(host, C_IN, T_A, answer, sizeof(answer)); 117 118 if ((status == -1) && Eflag) 119 status = res_search(host, C_IN, T_MX, answer, sizeof(answer)); 120 121 return(status == -1); 122 } 123 124 void 125 capitalize(name,len) 126 char *name; 127 int len; 128 { 129 char last = ' '; 130 char *c; 131 int i = 0; 132 133 for(c = name; i < len; i++) { 134 if (*c == '.') last = '.'; 135 c++; 136 } 137 138 i = 0; 139 if (last == '.') { 140 for(c = name; i < len; i++) { 141 if (last == '.') { 142 *c = toupper(*c); 143 } 144 last = *c++; 145 } 146 } 147 148 } 149 150 int 151 main (argc,argv) 152 int argc; 153 char *argv[]; 154 { 155 int usage = 0; 156 int eflag = 0; 157 int dflag = 0; 158 int nflag = 0; 159 int sflag = 0; 160 int uflag = 0; 161 int vflag = 0; 162 int Eflag = 0; 163 int ch, fd; 164 char *input = NULL; 165 char *output = NULL; 166 DBM *db; 167 datum key,val; 168 char *slash; 169 DBM *new_db = NULL; 170 static char mapname[] = "ypdbXXXXXXXXXX"; 171 char db_mapname[MAXPATHLEN],db_outfile[MAXPATHLEN], 172 db_tempname[MAXPATHLEN]; 173 int status; 174 char user[4096],host[4096]; /* XXX: DB bsize = 4096 in ypdb.c */ 175 char datestr[11]; 176 char myname[MAXHOSTNAMELEN]; 177 178 while ((ch = getopt(argc, argv, "Edensuv")) != -1) 179 switch(ch) { 180 case 'E': 181 eflag++; /* Check hostname */ 182 Eflag++; /* .. even check MX records */ 183 break; 184 case 'd': 185 dflag++; /* Don't check DNS hostname */ 186 break; 187 case 'e': 188 eflag++; /* Check hostname */ 189 break; 190 case 'n': 191 nflag++; /* Capitalize name parts */ 192 break; 193 case 's': 194 sflag++; /* Don't know... */ 195 break; 196 case 'u': 197 uflag++; /* Don't check UUCP hostname */ 198 break; 199 case 'v': 200 vflag++; /* Verbose */ 201 break; 202 default: 203 usage++; 204 break; 205 } 206 207 if (optind == argc) { 208 usage++; 209 } else { 210 input = argv[optind++]; 211 if (optind < argc) 212 output = argv[optind++]; 213 if (optind < argc) 214 usage++; 215 } 216 217 if (usage) { 218 fprintf(stderr, 219 "usage: %s [-v] [-e|-E [-d] [-u]] [-n] input [output]\n", 220 __progname); 221 exit(1); 222 } 223 224 db = ypdb_open(input, O_RDONLY, 0444); 225 if (db == NULL) { 226 fprintf(stderr, 227 "%s: Unable to open input database %s\n", 228 __progname, 229 input); 230 exit(1); 231 } 232 233 if (output != NULL) { 234 if (strlen(output) + strlen(YPDB_SUFFIX) > MAXPATHLEN) { 235 fprintf(stderr,"%s: %s: file name too long\n", 236 __progname, output); 237 } 238 snprintf(db_outfile, sizeof(db_outfile), 239 "%s%s", output, YPDB_SUFFIX); 240 241 slash = strrchr(output, '/'); 242 if (slash != NULL) 243 slash[1] = 0; /* truncate to dir */ 244 else 245 *output = 0; /* elminate */ 246 247 /* note: output is now directory where map goes ! */ 248 249 if (strlen(output) + strlen(mapname) 250 + strlen(YPDB_SUFFIX) > MAXPATHLEN) { 251 fprintf(stderr,"%s: %s: directory name too long\n", 252 __progname, output); 253 exit(1); 254 } 255 256 snprintf(db_tempname, sizeof(db_tempname), "%s%s", output, 257 mapname); 258 fd = mkstemp(db_tempname); 259 if (fd == -1) 260 goto fail; 261 close(fd); 262 263 snprintf(db_mapname, sizeof(db_mapname), "%s%s", db_tempname, 264 YPDB_SUFFIX); 265 new_db = ypdb_open(db_tempname, O_RDWR|O_CREAT, 0444); 266 if (new_db == NULL) { 267 fail: 268 if (fd != -1) 269 unlink(db_tempname); 270 fprintf(stderr, 271 "%s: Unable to open output database %s\n", 272 __progname, 273 db_outfile); 274 exit(1); 275 } 276 } 277 278 for (key = ypdb_firstkey(db); 279 key.dptr != NULL; 280 key = ypdb_nextkey(db)) { 281 282 val = ypdb_fetch(db,key); 283 284 if (val.dptr == NULL) continue; /* No value */ 285 if ((*key.dptr == '@') && (key.dsize == 1)) 286 continue; /* Sendmail token */ 287 if (strncmp(key.dptr, "YP_", 3)==0) /* YP token */ 288 continue; 289 if (index(val.dptr,',')) continue; /* List... */ 290 if (index(val.dptr,'|')) continue; /* Pipe... */ 291 292 if (!((index(val.dptr,'@')) || 293 (index(val.dptr,'!')))) continue; /* Skip local users */ 294 295 split_address(val.dptr,val.dsize,user,host); 296 297 if (eflag && check_host(val.dptr, host, dflag, uflag, Eflag)) { 298 printf("Invalid host %s in %*.*s:%*.*s\n", 299 host, 300 key.dsize, key.dsize, key.dptr, 301 val.dsize, val.dsize, val.dptr); 302 continue; 303 } 304 305 if (nflag) { 306 capitalize(key.dptr,key.dsize); 307 } 308 309 if (new_db != NULL) { 310 status = ypdb_store(new_db, val, key, YPDB_INSERT); 311 if (status != 0) { 312 printf("%s: problem storing %*.*s %*.*s\n", 313 __progname, 314 val.dsize, val.dsize, val.dptr, 315 key.dsize, key.dsize, key.dptr); 316 } 317 } 318 319 if (vflag) { 320 printf("%*.*s --> %*.*s\n", 321 val.dsize, val.dsize, val.dptr, 322 key.dsize, key.dsize, key.dptr); 323 } 324 325 } 326 327 if (new_db != NULL) { 328 snprintf(datestr, sizeof datestr, "%010u", time(NULL)); 329 key.dptr = YP_LAST_KEY; 330 key.dsize = strlen(YP_LAST_KEY); 331 val.dptr = datestr; 332 val.dsize = strlen(datestr); 333 status = ypdb_store(new_db, key, val, YPDB_INSERT); 334 if (status != 0) { 335 printf("%s: problem storing %*.*s %*.*s\n", 336 __progname, 337 key.dsize, key.dsize, key.dptr, 338 val.dsize, val.dsize, val.dptr); 339 } 340 } 341 342 if (new_db != NULL) { 343 gethostname(myname, sizeof(myname)); 344 key.dptr = YP_MASTER_KEY; 345 key.dsize = strlen(YP_MASTER_KEY); 346 val.dptr = myname; 347 val.dsize = strlen(myname); 348 status = ypdb_store(new_db, key, val, YPDB_INSERT); 349 if (status != 0) { 350 printf("%s: problem storing %*.*s %*.*s\n", 351 __progname, 352 key.dsize, key.dsize, key.dptr, 353 val.dsize, val.dsize, val.dptr); 354 } 355 } 356 357 358 359 ypdb_close(db); 360 361 if (new_db != NULL) { 362 ypdb_close(new_db); 363 if (rename(db_mapname,db_outfile) < 0) { 364 perror("rename"); 365 fprintf(stderr,"rename %s -> %s failed!\n", db_mapname, 366 db_outfile); 367 exit(1); 368 } 369 } 370 371 return(0); 372 373 } 374