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