1 /* $NetBSD: mkalias.c,v 1.13 2005/06/20 00:08:35 lukem 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 #include <sys/cdefs.h> 35 #ifndef lint 36 __RCSID("$NetBSD: mkalias.c,v 1.13 2005/06/20 00:08:35 lukem Exp $"); 37 #endif 38 39 #include <sys/types.h> 40 #include <sys/param.h> 41 #include <netinet/in.h> 42 #include <arpa/nameser.h> 43 44 #include <ctype.h> 45 #include <err.h> 46 #include <fcntl.h> 47 #include <netdb.h> 48 #include <resolv.h> 49 #include <stdio.h> 50 #include <stdlib.h> 51 #include <string.h> 52 #include <time.h> 53 #include <unistd.h> 54 55 #include <rpc/rpc.h> 56 57 #include "protos.h" 58 #include "ypdb.h" 59 #include "ypdef.h" 60 61 void capitalize(char *, int); 62 int check_host(char *, char *, int, int, int); 63 int main(int, char *[]); 64 void split_address(char *, int, char *, char *); 65 void usage(void); 66 67 void 68 split_address(char *address, int len, char *user, char *host) 69 { 70 char *c, *s, *r; 71 int i = 0; 72 73 if ((strchr(address, '@')) != NULL) { 74 75 s = user; 76 77 for(c = address; i < len; i++) { 78 if (*c == '@') { 79 *s = '\0'; 80 s = host; 81 } else 82 *s++ = *c; 83 c++; 84 } 85 *s = '\0'; 86 } 87 88 if ((r = strrchr(address, '!')) != NULL) { 89 90 s = host; 91 92 for(c = address; i < len; i++) { 93 if (c == r) { 94 *s = '\0'; 95 s = user; 96 } else 97 *s++ = *c; 98 c++; 99 } 100 *s = '\0'; 101 } 102 } 103 104 int 105 check_host(char *address, char *host, int dflag, int uflag, int Eflag) 106 { 107 char answer[PACKETSZ]; 108 int status; 109 110 if ((dflag && strchr(address, '@')) || 111 (uflag && strchr(address, '!'))) 112 return(0); 113 114 if ((_res.options & RES_INIT) == 0) 115 res_init(); 116 117 status = res_search(host, C_IN, T_AAAA, answer, sizeof(answer)); 118 119 if (status == -1) 120 status = res_search(host, C_IN, T_A, answer, sizeof(answer)); 121 122 if ((status == -1) && Eflag) 123 status = res_search(host, C_IN, T_MX, answer, sizeof(answer)); 124 125 return(status == -1); 126 } 127 128 void 129 capitalize(char *name, int len) 130 { 131 char last = ' '; 132 char *c; 133 int i = 0; 134 135 for(c = name; i < len; i++) { 136 if (*c == '.') last = '.'; 137 c++; 138 } 139 140 i = 0; 141 if (last == '.') { 142 for(c = name; i < len; i++) { 143 if (last == '.') 144 *c = toupper((unsigned char)*c); 145 last = *c++; 146 } 147 } 148 } 149 150 int 151 main(int argc, char *argv[]) 152 { 153 int eflag = 0; 154 int dflag = 0; 155 int nflag = 0; 156 int sflag = 0; 157 int uflag = 0; 158 int vflag = 0; 159 int Eflag = 0; 160 int ch; 161 char *input = NULL; 162 char *output = NULL; 163 DBM *db; 164 datum key, val; 165 char *slash; 166 DBM *new_db = NULL; 167 static char mapname[] = "ypdbXXXXXXXXXX"; 168 char db_mapname[MAXPATHLEN], db_outfile[MAXPATHLEN], 169 db_tempname[MAXPATHLEN]; 170 int status; 171 char user[4096], host[4096]; /* XXX: DB bsize = 4096 in ypdb.c */ 172 char datestr[11]; 173 char myname[MAXHOSTNAMELEN]; 174 175 while ((ch = getopt(argc, argv, "Edensuv")) != -1) { 176 switch(ch) { 177 case 'd': 178 dflag++; /* Don't check DNS hostname */ 179 break; 180 181 case 'e': 182 eflag++; /* Check hostname */ 183 break; 184 185 case 'E': 186 eflag++; /* Check hostname */ 187 Eflag++; /* .. even check MX records */ 188 break; 189 190 case 'n': 191 nflag++; /* Capitalize name parts */ 192 break; 193 194 case 's': 195 sflag++; /* Don't know... */ 196 break; 197 198 case 'u': 199 uflag++; /* Don't check UUCP hostname */ 200 break; 201 202 case 'v': 203 vflag++; /* Verbose */ 204 break; 205 206 default: 207 usage(); 208 } 209 } 210 211 if (optind == argc) 212 usage(); 213 214 input = argv[optind++]; 215 if (optind < argc) 216 output = argv[optind++]; 217 if (optind < argc) 218 usage(); 219 220 db = ypdb_open(input, O_RDONLY, 0444); 221 if (db == NULL) 222 err(1, "Unable to open input database `%s'", input); 223 224 if (output != NULL) { 225 if (strlen(output) + strlen(YPDB_SUFFIX) > 226 (sizeof(db_outfile) + 1)) 227 warnx("file name `%s' too long", output); 228 snprintf(db_outfile, sizeof(db_outfile), 229 "%s%s", output, YPDB_SUFFIX); 230 231 slash = strrchr(output, '/'); 232 if (slash != NULL) 233 slash[1] = 0; /* truncate to dir */ 234 else 235 *output = 0; /* elminate */ 236 237 /* note: output is now directory where map goes ! */ 238 239 if (strlen(output) + strlen(mapname) + strlen(YPDB_SUFFIX) > 240 (sizeof(db_mapname) - 1)) 241 errx(1, "Directory name `%s' too long", output); 242 243 snprintf(db_tempname, sizeof(db_tempname), "%s%s", output, 244 mapname); 245 mktemp(db_tempname); /* OK */ 246 snprintf(db_mapname, sizeof(db_mapname), "%s%s", db_tempname, 247 YPDB_SUFFIX); 248 249 new_db = ypdb_open(db_tempname, O_RDWR|O_CREAT, 0444); 250 if (new_db == NULL) 251 err(1, "Unable to open output database `%s'", 252 db_outfile); 253 } 254 255 for (key = ypdb_firstkey(db); 256 key.dptr != NULL; 257 key = ypdb_nextkey(db)) { 258 259 val = ypdb_fetch(db, key); 260 261 if (val.dptr == NULL) 262 continue; /* No value */ 263 if ((*key.dptr == '@') && (key.dsize == 1)) 264 continue; /* Sendmail token */ 265 if (strncmp(key.dptr, "YP_", 3)==0) /* YP token */ 266 continue; 267 if (strchr(val.dptr, ',')) /* List... */ 268 continue; 269 if (strchr(val.dptr, '|')) /* Pipe... */ 270 continue; 271 272 if (!((strchr(val.dptr, '@')) || 273 (strchr(val.dptr, '!')))) 274 continue; /* Skip local users */ 275 276 split_address(val.dptr, val.dsize, user, host); 277 278 if (eflag && check_host(val.dptr, host, dflag, uflag, Eflag)) { 279 printf("Invalid host %s in %*.*s:%*.*s\n", host, 280 key.dsize, key.dsize, key.dptr, 281 val.dsize, val.dsize, val.dptr); 282 continue; 283 } 284 285 if (nflag) 286 capitalize(key.dptr, key.dsize); 287 288 if (new_db != NULL) { 289 status = ypdb_store(new_db, val, key, YPDB_INSERT); 290 if (status != 0) { 291 printf("%s: problem storing %*.*s %*.*s\n", 292 getprogname(), 293 val.dsize, val.dsize, val.dptr, 294 key.dsize, key.dsize, key.dptr); 295 } 296 } 297 298 if (vflag) { 299 printf("%*.*s --> %*.*s\n", 300 val.dsize, val.dsize, val.dptr, 301 key.dsize, key.dsize, key.dptr); 302 } 303 304 } 305 306 if (new_db != NULL) { 307 snprintf(datestr, sizeof(datestr), "%010d", (int)time(NULL)); 308 key.dptr = YP_LAST_KEY; 309 key.dsize = strlen(YP_LAST_KEY); 310 val.dptr = datestr; 311 val.dsize = strlen(datestr); 312 status = ypdb_store(new_db, key, val, YPDB_INSERT); 313 if (status != 0) 314 warnx("problem storing %*.*s %*.*s", 315 key.dsize, key.dsize, key.dptr, 316 val.dsize, val.dsize, val.dptr); 317 } 318 319 if (new_db != NULL) { 320 localhostname(myname, sizeof(myname) - 1); 321 key.dptr = YP_MASTER_KEY; 322 key.dsize = strlen(YP_MASTER_KEY); 323 val.dptr = myname; 324 val.dsize = strlen(myname); 325 status = ypdb_store(new_db, key, val, YPDB_INSERT); 326 if (status != 0) 327 warnx("problem storing %*.*s %*.*s", 328 key.dsize, key.dsize, key.dptr, 329 val.dsize, val.dsize, val.dptr); 330 } 331 332 ypdb_close(db); 333 334 if (new_db != NULL) { 335 ypdb_close(new_db); 336 if (rename(db_mapname, db_outfile) < 0) 337 err(1, "rename `%s' to `%s' failed", db_mapname, 338 db_outfile); 339 } 340 341 exit(0); 342 } 343 344 void 345 usage(void) 346 { 347 fprintf(stderr, 348 "usage: %s [-e|-E [-d] [-u]] [-n] [-v] input [output]\n", 349 getprogname()); 350 exit(1); 351 } 352