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