1 /* $OpenBSD: getent.c,v 1.6 2013/03/30 14:03:08 florian Exp $ */ 2 /* $NetBSD: getent.c,v 1.7 2005/08/24 14:31:02 ginsbach Exp $ */ 3 4 /*- 5 * Copyright (c) 2004 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Luke Mewburn. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/types.h> 34 #include <sys/socket.h> 35 36 #include <ctype.h> 37 #include <errno.h> 38 #include <grp.h> 39 #include <limits.h> 40 #include <netdb.h> 41 #include <pwd.h> 42 #include <stdio.h> 43 #include <stdarg.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <unistd.h> 47 48 #include <net/if.h> 49 #include <netinet/in.h> /* for INET6_ADDRSTRLEN */ 50 #include <netinet/if_ether.h> 51 52 #include <arpa/inet.h> 53 #include <arpa/nameser.h> 54 55 #include <rpc/rpc.h> 56 57 static int usage(void); 58 static int ethers(int, char *[]); 59 static int group(int, char *[]); 60 static int hosts(int, char *[]); 61 static int networks(int, char *[]); 62 static int passwd(int, char *[]); 63 static int protocols(int, char *[]); 64 static int rpc(int, char *[]); 65 static int services(int, char *[]); 66 static int shells(int, char *[]); 67 extern char *__progname; 68 69 enum { 70 RV_OK = 0, 71 RV_USAGE = 1, 72 RV_NOTFOUND = 2, 73 RV_NOENUM = 3 74 }; 75 76 static struct getentdb { 77 const char *name; 78 int (*fn)(int, char *[]); 79 } databases[] = { 80 { "ethers", ethers, }, 81 { "group", group, }, 82 { "hosts", hosts, }, 83 { "networks", networks, }, 84 { "passwd", passwd, }, 85 { "protocols", protocols, }, 86 { "rpc", rpc, }, 87 { "services", services, }, 88 { "shells", shells, }, 89 90 { NULL, NULL, }, 91 }; 92 93 int 94 main(int argc, char *argv[]) 95 { 96 struct getentdb *curdb; 97 98 if (argc < 2) 99 usage(); 100 for (curdb = databases; curdb->name != NULL; curdb++) { 101 if (strcmp(curdb->name, argv[1]) == 0) { 102 exit(curdb->fn(argc, argv)); 103 break; 104 } 105 } 106 fprintf(stderr, "%s: unknown database: %s\n", __progname, argv[1]); 107 return RV_USAGE; 108 } 109 110 static int 111 usage(void) 112 { 113 fprintf(stderr, "usage: %s database [key ...]\n", __progname); 114 exit(RV_USAGE); 115 /* NOTREACHED */ 116 } 117 118 /* 119 * printfmtstrings -- 120 * vprintf(format, ...), 121 * then the aliases (beginning with prefix, separated by sep), 122 * then a newline 123 */ 124 static void 125 printfmtstrings(char *strings[], const char *prefix, const char *sep, 126 const char *fmt, ...) 127 { 128 va_list ap; 129 const char *curpref; 130 int i; 131 132 va_start(ap, fmt); 133 vprintf(fmt, ap); 134 va_end(ap); 135 136 curpref = prefix; 137 for (i = 0; strings[i] != NULL; i++) { 138 printf("%s%s", curpref, strings[i]); 139 curpref = sep; 140 } 141 printf("\n"); 142 } 143 144 #define ETHERSPRINT printf("%-17s %s\n", ether_ntoa(eap), hp) 145 146 static int 147 ethers(int argc, char *argv[]) 148 { 149 char hostname[MAXHOSTNAMELEN], *hp; 150 int i, rv = RV_OK; 151 struct ether_addr ea, *eap; 152 153 if (argc == 2) { 154 fprintf(stderr, "%s: Enumeration not supported on ethers\n", 155 __progname); 156 rv = RV_NOENUM; 157 } else { 158 for (i = 2; i < argc; i++) { 159 if ((eap = ether_aton(argv[i])) == NULL) { 160 eap = &ea; 161 hp = argv[i]; 162 if (ether_hostton(hp, eap) != 0) { 163 rv = RV_NOTFOUND; 164 break; 165 } 166 } else { 167 hp = hostname; 168 if (ether_ntohost(hp, eap) != 0) { 169 rv = RV_NOTFOUND; 170 break; 171 } 172 } 173 ETHERSPRINT; 174 } 175 } 176 return rv; 177 } 178 179 #define GROUPPRINT \ 180 printfmtstrings(gr->gr_mem, ":", ",", "%s:%s:%u", \ 181 gr->gr_name, gr->gr_passwd, gr->gr_gid) 182 183 static int 184 group(int argc, char *argv[]) 185 { 186 int i, rv = RV_OK; 187 struct group *gr; 188 189 setgroupent(1); 190 if (argc == 2) { 191 while ((gr = getgrent()) != NULL) 192 GROUPPRINT; 193 } else { 194 for (i = 2; i < argc; i++) { 195 const char *err; 196 long long id = strtonum(argv[i], 0, UINT_MAX, &err); 197 198 if (!err) 199 gr = getgrgid((gid_t)id); 200 else 201 gr = getgrnam(argv[i]); 202 if (gr != NULL) 203 GROUPPRINT; 204 else { 205 rv = RV_NOTFOUND; 206 break; 207 } 208 } 209 } 210 endgrent(); 211 return rv; 212 } 213 214 static void 215 hostsprint(const struct hostent *he) 216 { 217 char buf[INET6_ADDRSTRLEN]; 218 219 if (inet_ntop(he->h_addrtype, he->h_addr, buf, sizeof(buf)) == NULL) 220 strlcpy(buf, "# unknown", sizeof(buf)); 221 printfmtstrings(he->h_aliases, " ", " ", "%-16s %s", buf, he->h_name); 222 } 223 static int 224 hostsaddrinfo(char* name) 225 { 226 struct addrinfo hints, *res, *res0; 227 void *src; 228 int rv; 229 char buf[INET6_ADDRSTRLEN]; 230 231 rv = RV_NOTFOUND; 232 memset(buf, 0, sizeof(buf)); 233 memset(&hints, 0, sizeof(hints)); 234 hints.ai_family = PF_UNSPEC; 235 hints.ai_socktype = SOCK_DGRAM; 236 237 if (getaddrinfo(name, NULL, &hints, &res0) == 0) { 238 for (res = res0; res; res = res->ai_next) { 239 switch (res->ai_family) { 240 case AF_INET: 241 src = &((struct sockaddr_in*) 242 res->ai_addr)->sin_addr; 243 break; 244 case AF_INET6: 245 src = &((struct sockaddr_in6*) 246 res->ai_addr)->sin6_addr; 247 break; 248 default: /* not reached */ 249 src = NULL; 250 } 251 if (src==NULL || inet_ntop(res->ai_family, src, buf, 252 sizeof(buf)) == NULL) 253 strlcpy(buf, "# unknown", sizeof(buf)); 254 else 255 rv = RV_OK; 256 printf("%-39s %s\n", buf, name); 257 } 258 freeaddrinfo(res0); 259 } 260 261 return (rv); 262 } 263 264 static int 265 hosts(int argc, char *argv[]) 266 { 267 char addr[IN6ADDRSZ]; 268 int i, rv = RV_OK; 269 struct hostent *he; 270 271 sethostent(1); 272 if (argc == 2) { 273 while ((he = gethostent()) != NULL) 274 hostsprint(he); 275 } else { 276 for (i = 2; i < argc; i++) { 277 he = NULL; 278 if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0) 279 he = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6); 280 else if (inet_pton(AF_INET, argv[i], (void *)addr) > 0) 281 he = gethostbyaddr(addr, INADDRSZ, AF_INET); 282 if (he != NULL) 283 hostsprint(he); 284 else if ((rv = hostsaddrinfo(argv[i])) == RV_NOTFOUND) 285 break; 286 } 287 } 288 endhostent(); 289 return rv; 290 } 291 292 static void 293 networksprint(const struct netent *ne) 294 { 295 char buf[INET6_ADDRSTRLEN]; 296 struct in_addr ianet; 297 298 ianet = inet_makeaddr(ne->n_net, 0); 299 if (inet_ntop(ne->n_addrtype, &ianet, buf, sizeof(buf)) == NULL) 300 strlcpy(buf, "# unknown", sizeof(buf)); 301 printfmtstrings(ne->n_aliases, " ", " ", "%-16s %s", ne->n_name, buf); 302 } 303 304 static int 305 networks(int argc, char *argv[]) 306 { 307 int i, rv = RV_OK; 308 struct netent *ne; 309 in_addr_t net; 310 311 setnetent(1); 312 if (argc == 2) { 313 while ((ne = getnetent()) != NULL) 314 networksprint(ne); 315 } else { 316 for (i = 2; i < argc; i++) { 317 net = inet_network(argv[i]); 318 if (net != INADDR_NONE) 319 ne = getnetbyaddr(net, AF_INET); 320 else 321 ne = getnetbyname(argv[i]); 322 if (ne != NULL) 323 networksprint(ne); 324 else { 325 rv = RV_NOTFOUND; 326 break; 327 } 328 } 329 } 330 endnetent(); 331 return rv; 332 } 333 334 #define PASSWDPRINT \ 335 printf("%s:%s:%u:%u:%s:%s:%s\n", \ 336 pw->pw_name, pw->pw_passwd, pw->pw_uid, \ 337 pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell) 338 339 static int 340 passwd(int argc, char *argv[]) 341 { 342 int i, rv = RV_OK; 343 struct passwd *pw; 344 345 setpassent(1); 346 if (argc == 2) { 347 while ((pw = getpwent()) != NULL) 348 PASSWDPRINT; 349 } else { 350 for (i = 2; i < argc; i++) { 351 const char *err; 352 long long id = strtonum(argv[i], 0, UINT_MAX, &err); 353 354 if (!err) 355 pw = getpwuid((uid_t)id); 356 else 357 pw = getpwnam(argv[i]); 358 if (pw != NULL) 359 PASSWDPRINT; 360 else { 361 rv = RV_NOTFOUND; 362 break; 363 } 364 } 365 } 366 endpwent(); 367 return rv; 368 } 369 370 #define PROTOCOLSPRINT \ 371 printfmtstrings(pe->p_aliases, " ", " ", \ 372 "%-16s %5d", pe->p_name, pe->p_proto) 373 374 static int 375 protocols(int argc, char *argv[]) 376 { 377 struct protoent *pe; 378 int i, rv = RV_OK; 379 380 setprotoent(1); 381 if (argc == 2) { 382 while ((pe = getprotoent()) != NULL) 383 PROTOCOLSPRINT; 384 } else { 385 for (i = 2; i < argc; i++) { 386 const char *err; 387 long long id = strtonum(argv[i], 0, UINT_MAX, &err); 388 389 if (!err) 390 pe = getprotobynumber((int)id); 391 else 392 pe = getprotobyname(argv[i]); 393 if (pe != NULL) 394 PROTOCOLSPRINT; 395 else { 396 rv = RV_NOTFOUND; 397 break; 398 } 399 } 400 } 401 endprotoent(); 402 return rv; 403 } 404 405 #define RPCPRINT \ 406 printfmtstrings(re->r_aliases, " ", " ", \ 407 "%-16s %6d", re->r_name, re->r_number) 408 409 static int 410 rpc(int argc, char *argv[]) 411 { 412 struct rpcent *re; 413 int i, rv = RV_OK; 414 415 setrpcent(1); 416 if (argc == 2) { 417 while ((re = getrpcent()) != NULL) 418 RPCPRINT; 419 } else { 420 for (i = 2; i < argc; i++) { 421 const char *err; 422 long long id = strtonum(argv[i], 0, UINT_MAX, &err); 423 424 if (!err) 425 re = getrpcbynumber((int)id); 426 else 427 re = getrpcbyname(argv[i]); 428 if (re != NULL) 429 RPCPRINT; 430 else { 431 rv = RV_NOTFOUND; 432 break; 433 } 434 } 435 } 436 endrpcent(); 437 return rv; 438 } 439 440 #define SERVICESPRINT \ 441 printfmtstrings(se->s_aliases, " ", " ", \ 442 "%-16s %5d/%s", se->s_name, ntohs(se->s_port), se->s_proto) 443 444 static int 445 services(int argc, char *argv[]) 446 { 447 struct servent *se; 448 int i, rv = RV_OK; 449 450 setservent(1); 451 if (argc == 2) { 452 while ((se = getservent()) != NULL) 453 SERVICESPRINT; 454 } else { 455 for (i = 2; i < argc; i++) { 456 const char *err; 457 long long id; 458 char *proto = strchr(argv[i], '/'); 459 460 if (proto != NULL) 461 *proto++ = '\0'; 462 id = strtonum(argv[i], 0, UINT_MAX, &err); 463 if (!err) 464 se = getservbyport(htons((u_short)id), proto); 465 else 466 se = getservbyname(argv[i], proto); 467 if (se != NULL) 468 SERVICESPRINT; 469 else { 470 rv = RV_NOTFOUND; 471 break; 472 } 473 } 474 } 475 endservent(); 476 return rv; 477 } 478 479 #define SHELLSPRINT printf("%s\n", sh) 480 481 static int 482 shells(int argc, char *argv[]) 483 { 484 const char *sh; 485 int i, rv = RV_OK; 486 487 setusershell(); 488 if (argc == 2) { 489 while ((sh = getusershell()) != NULL) 490 SHELLSPRINT; 491 } else { 492 for (i = 2; i < argc; i++) { 493 setusershell(); 494 while ((sh = getusershell()) != NULL) { 495 if (strcmp(sh, argv[i]) == 0) { 496 SHELLSPRINT; 497 break; 498 } 499 } 500 if (sh == NULL) { 501 rv = RV_NOTFOUND; 502 break; 503 } 504 } 505 } 506 endusershell(); 507 return rv; 508 } 509