| /* |
| * CDDL HEADER START |
| * |
| * The contents of this file are subject to the terms of the |
| * Common Development and Distribution License (the "License"). |
| * You may not use this file except in compliance with the License. |
| * |
| * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
| * or http://www.opensolaris.org/os/licensing. |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| * |
| * When distributing Covered Code, include this CDDL HEADER in each |
| * file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
| * If applicable, add the following below this CDDL HEADER, with the |
| * fields enclosed by brackets "[]" replaced with your own identifying |
| * information: Portions Copyright [yyyy] [name of copyright owner] |
| * |
| * CDDL HEADER END |
| */ |
| /* |
| * Copyright 2006 Sun Microsystems, Inc. All rights reserved. |
| * Use is subject to license terms. |
| */ |
| |
| #pragma ident "%Z%%M% %I% %E% SMI" |
| |
| /* |
| * ldapaddent.c |
| * |
| * Utility to add /etc files into LDAP. |
| * Can also be used to dump entries from a ldap container in /etc format. |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <libintl.h> |
| #include <strings.h> |
| #include <sys/param.h> |
| #include <ctype.h> |
| #include <sys/types.h> |
| #include <sys/socket.h> |
| #include <netinet/in.h> |
| #include <arpa/inet.h> |
| #include <locale.h> |
| #include <syslog.h> |
| |
| #undef opaque |
| |
| #include <nss_dbdefs.h> |
| #include <netdb.h> |
| #include <rpc/rpcent.h> |
| #include <grp.h> |
| #include <pwd.h> |
| #include <shadow.h> |
| #include <sys/systeminfo.h> |
| #include "ns_internal.h" |
| #include "ldapaddent.h" |
| |
| #define OP_ADD 0 |
| #define OP_DUMP 3 |
| |
| static struct ttypelist_t { |
| char *ttype; /* type tag */ |
| int (*genent)(char *, int(*)()); |
| /* routine to turn line into ldap entries */ |
| void (*dump)(ns_ldap_result_t *); |
| /* routine to print ldap containers */ |
| int (*filedbmline)(); /* routine to turn file line into dbm line */ |
| char *objclass; /* Objectclass for the servicetype */ |
| } *tt; |
| |
| char parse_err_msg [PARSE_ERR_MSG_LEN]; |
| int continue_onerror = 0; /* do not exit on error */ |
| |
| static int get_basedn(char *service, char **basedn); |
| static int check_ipaddr(char *addr, char **newaddr); |
| |
| extern int optind; |
| extern char *optarg; |
| |
| extern char *__nis_quote_key(const char *, char *, int); |
| /* from ns_internal.h */ |
| extern int __s_api_prepend_automountmapname_to_dn( |
| const char *, char **, ns_ldap_error_t **); |
| |
| static char *inputbasedn = NULL; |
| static char *databasetype = NULL; |
| static int exit_val = 0; |
| static unsigned nent_add = 0; |
| static FILE *etcf = 0; |
| static ns_cred_t authority; |
| unsigned flags = 0; |
| |
| static void |
| perr(ns_ldap_error_t *e) |
| { |
| if (e) |
| (void) fprintf(stderr, gettext("%d: %s\n"), |
| e->status, e->message); |
| } |
| |
| |
| static int |
| ascii_to_int(char *str) |
| { |
| int i; |
| char *c = str; |
| |
| if (c == NULL || *c == '\0') |
| return (-1); |
| |
| while (c != '\0' && *c == ' ') |
| c++; |
| if (*c == '\0') |
| return (-1); |
| |
| for (i = 0; i < strlen(c); i++) |
| if (!isdigit(c[i])) |
| return (-1); |
| |
| return (atoi(c)); |
| } |
| |
| /* |
| * Internet network address interpretation routine. |
| * The library routines call this routine to interpret |
| * network numbers. |
| */ |
| static in_addr_t |
| encode_network(const char *cp) |
| { |
| in_addr_t val; |
| int base; |
| ptrdiff_t n; |
| char c; |
| in_addr_t parts[4], *pp = parts; |
| int i; |
| |
| again: |
| val = 0; base = 10; |
| if (*cp == '0') { |
| if (*++cp == 'x' || *cp == 'X') |
| base = 16, cp++; |
| else |
| base = 8; |
| } |
| while ((c = *cp) != NULL) { |
| if (isdigit(c)) { |
| if ((c - '0') >= base) |
| break; |
| val = (val * base) + (c - '0'); |
| cp++; |
| continue; |
| } |
| if (base == 16 && isxdigit(c)) { |
| val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A')); |
| cp++; |
| continue; |
| } |
| break; |
| } |
| if (*cp == '.') { |
| if (pp >= parts + 4) |
| return ((in_addr_t)-1); |
| *pp++ = val, cp++; |
| goto again; |
| } |
| if (*cp && !isspace(*cp)) |
| return ((in_addr_t)-1); |
| *pp++ = val; |
| n = pp - parts; |
| if (n > 4) |
| return ((in_addr_t)-1); |
| for (val = 0, i = 0; i < n; i++) { |
| val <<= 8; |
| val |= parts[i] & 0xff; |
| } |
| for (/* no init */; i < 4; i++) |
| val <<= 8; |
| return (val); |
| } |
| |
| static void |
| replace_tab2space(char *str) |
| { |
| int i = 0; |
| |
| while ((str) && (str[i])) { |
| if (str[i] == '\t') |
| str[i] = ' '; |
| i++; |
| } |
| } |
| |
| static int |
| blankline(char *line) |
| { |
| char *p; |
| |
| for (p = line; *p; p++) |
| if (*p != ' ' && *p != '\t') |
| return (0); |
| return (1); |
| } |
| |
| /* |
| * check whether the token <tok> is a triplet, |
| * i. e. <tok> := (<hostname>,<username>,<domainname>) |
| * where <hostname>, <username>, <domainname> are IA5String |
| * <tok> supposes to contain NO spaces and start with '(' |
| */ |
| static int |
| is_triplet(char *tok) |
| { |
| char *s; |
| return (strchr(++tok, '(') == NULL && /* no more '(' */ |
| (s = strchr(tok, ')')) != NULL && /* find ')' */ |
| !*++s && /* ')' ends token */ |
| (tok = strchr(tok, ',')) != NULL && /* host up to ',' */ |
| (tok = strchr(++tok, ',')) != NULL && /* user up to ',' */ |
| strchr(++tok, ',') == NULL); /* no more ',' */ |
| } |
| |
| static void |
| line_buf_expand(struct line_buf *line) |
| { |
| line->alloc += BUFSIZ; |
| line->str = (char *)realloc(line->str, line->alloc); |
| |
| if (line->str == NULL) { |
| (void) fprintf(stderr, |
| gettext("line_buf_expand: out of memory\n")); |
| exit(1); |
| } |
| } |
| |
| static void |
| line_buf_init(struct line_buf *line) |
| { |
| (void) memset((char *)line, 0, sizeof (*line)); |
| line_buf_expand(line); |
| } |
| |
| static int |
| __s_add_attr(ns_ldap_entry_t *e, char *attrname, char *value) |
| { |
| ns_ldap_attr_t *a; |
| char *v; |
| |
| a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t)); |
| if (a == NULL) |
| return (NS_LDAP_MEMORY); |
| a->attrname = strdup(attrname); |
| if (a->attrname == NULL) { |
| free(a); |
| return (NS_LDAP_MEMORY); |
| } |
| a->attrvalue = (char **)calloc(1, sizeof (char **)); |
| if (a->attrvalue == NULL) { |
| free(a->attrname); |
| free(a); |
| return (NS_LDAP_MEMORY); |
| } |
| a->value_count = 1; |
| a->attrvalue[0] = NULL; |
| v = strdup(value); |
| if (v == NULL) { |
| free(a->attrname); |
| free(a->attrvalue); |
| free(a); |
| return (NS_LDAP_MEMORY); |
| } |
| a->attrvalue[0] = v; |
| e->attr_pair[e->attr_count] = a; |
| e->attr_count++; |
| return (NS_LDAP_SUCCESS); |
| } |
| |
| static int |
| __s_add_attrlist(ns_ldap_entry_t *e, char *attrname, char **argv) |
| { |
| ns_ldap_attr_t *a; |
| char *v; |
| char **av; |
| int i, j; |
| |
| a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t)); |
| if (a == NULL) |
| return (NS_LDAP_MEMORY); |
| a->attrname = strdup(attrname); |
| if (a->attrname == NULL) { |
| free(a); |
| return (NS_LDAP_MEMORY); |
| } |
| |
| for (i = 0, av = argv; *av != NULL; av++, i++) |
| ; |
| |
| a->attrvalue = (char **)calloc(i, sizeof (char **)); |
| |
| if (a->attrvalue == NULL) { |
| free(a->attrname); |
| free(a); |
| return (NS_LDAP_MEMORY); |
| } |
| a->value_count = i; |
| for (j = 0; j < i; j++) { |
| v = strdup(argv[j]); |
| if (v == NULL) { |
| free(a->attrname); |
| free(a->attrvalue); |
| free(a); |
| return (NS_LDAP_MEMORY); |
| } |
| a->attrvalue[j] = v; |
| } |
| e->attr_pair[e->attr_count] = a; |
| e->attr_count++; |
| return (NS_LDAP_SUCCESS); |
| } |
| |
| static ns_ldap_entry_t * |
| __s_mk_entry(char **objclass, int max_attr) |
| { |
| ns_ldap_entry_t *e; |
| e = (ns_ldap_entry_t *)calloc(1, sizeof (ns_ldap_entry_t)); |
| if (e == NULL) |
| return (NULL); |
| e->attr_pair = (ns_ldap_attr_t **)calloc(max_attr+1, |
| sizeof (ns_ldap_attr_t *)); |
| if (e->attr_pair == NULL) { |
| free(e); |
| return (NULL); |
| } |
| e->attr_count = 0; |
| if (__s_add_attrlist(e, "objectClass", objclass) != NS_LDAP_SUCCESS) { |
| free(e->attr_pair); |
| free(e); |
| return (NULL); |
| } |
| return (e); |
| } |
| |
| static void |
| ldap_freeEntry(ns_ldap_entry_t *ep) |
| { |
| int j, k = 0; |
| |
| if (ep == NULL) |
| return; |
| |
| if (ep->attr_pair == NULL) { |
| free(ep); |
| return; |
| } |
| for (j = 0; j < ep->attr_count; j++) { |
| if (ep->attr_pair[j] == NULL) |
| continue; |
| if (ep->attr_pair[j]->attrname) |
| free(ep->attr_pair[j]->attrname); |
| if (ep->attr_pair[j]->attrvalue) { |
| for (k = 0; (k < ep->attr_pair[j]->value_count) && |
| (ep->attr_pair[j]->attrvalue[k]); k++) { |
| free(ep->attr_pair[j]->attrvalue[k]); |
| } |
| free(ep->attr_pair[j]->attrvalue); |
| } |
| free(ep->attr_pair[j]); |
| } |
| free(ep->attr_pair); |
| free(ep); |
| } |
| |
| static int |
| addentry(void *entry, int mod) |
| { |
| int result = 0; |
| ns_ldap_error_t *eres = NULL; |
| int rc = 1; |
| |
| |
| /* adds entry into the LDAP tree */ |
| if (mod) |
| result = __ns_ldap_addTypedEntry(databasetype, inputbasedn, |
| entry, 0, &authority, NS_LDAP_FOLLOWREF, &eres); |
| else |
| result = __ns_ldap_addTypedEntry(databasetype, inputbasedn, |
| entry, 1, &authority, NS_LDAP_FOLLOWREF, &eres); |
| /* |
| * Return 0 on success |
| * LDAP_ALREADY_EXISTS if entry exists already |
| * 1 for all other non-fatal errors. |
| * Exit on fatal errors. |
| */ |
| switch (result) { |
| case NS_LDAP_SUCCESS: |
| nent_add++; |
| rc = 0; |
| break; |
| |
| case NS_LDAP_OP_FAILED: |
| (void) fprintf(stderr, gettext("operation failed.\n")); |
| rc = 1; |
| break; |
| |
| case NS_LDAP_INVALID_PARAM: |
| (void) fprintf(stderr, |
| gettext("invalid parameter(s) passed.\n")); |
| rc = 1; |
| break; |
| |
| case NS_LDAP_NOTFOUND: |
| (void) fprintf(stderr, gettext("entry not found.\n")); |
| rc = 1; |
| break; |
| |
| case NS_LDAP_MEMORY: |
| (void) fprintf(stderr, |
| gettext("internal memory allocation error.\n")); |
| exit(1); |
| break; |
| |
| case NS_LDAP_CONFIG: |
| (void) fprintf(stderr, |
| gettext("LDAP Configuration problem.\n")); |
| perr(eres); |
| exit(1); |
| break; |
| |
| case NS_LDAP_PARTIAL: |
| (void) fprintf(stderr, |
| gettext("partial result returned\n")); |
| perr(eres); |
| rc = 1; |
| break; |
| |
| case NS_LDAP_INTERNAL: |
| if (eres->status == LDAP_ALREADY_EXISTS) |
| rc = eres->status; |
| else { |
| rc = 1; |
| perr(eres); |
| } |
| break; |
| } |
| |
| if (eres) |
| (void) __ns_ldap_freeError(&eres); |
| return (rc); |
| } |
| |
| |
| /* |
| * usage(char *msg) |
| * Display usage message to STDERR. |
| */ |
| static void |
| usage(char *msg) { |
| |
| if (msg) |
| (void) fprintf(stderr, gettext("%s\n"), msg); |
| |
| (void) fprintf(stderr, gettext( |
| "usage: ldapaddent [ -cpv ] [ -a authenticationMethod ]\n" |
| "[ -b baseDN ] -D bindDN -w bind_password [ -f file ] database\n\n" |
| "usage: ldapaddent -d [ -cpv ] [ -a authenticationMethod ]\n" |
| "[ -b baseDN ] [ -D bindDN ] [ -w bind_password ] database\n")); |
| exit(1); |
| } |
| |
| /* |
| * Determine if the given string is an IP address (IPv4 or IPv6). |
| * If so, it's converted to the preferred form (rfc2373) and |
| * *newaddr will point to the new address. |
| * |
| * Returns -2 : inet_ntop error |
| * -1 : not an IP address |
| * 0 : unsupported IP address (future use) |
| * AF_INET : IPv4 |
| * AF_INET6 : IPv6 |
| */ |
| static int |
| check_ipaddr(char *addr, char **newaddr) { |
| ipaddr_t addr_ipv4 = 0; |
| in6_addr_t addr_ipv6; |
| |
| /* IPv6 */ |
| if (inet_pton(AF_INET6, addr, &addr_ipv6) == 1) { |
| if (newaddr == NULL) |
| return (AF_INET6); |
| |
| /* Convert IPv4-mapped IPv6 address to IPv4 */ |
| if (IN6_IS_ADDR_V4MAPPED(&addr_ipv6) || |
| IN6_IS_ADDR_V4COMPAT(&addr_ipv6)) { |
| IN6_V4MAPPED_TO_IPADDR(&addr_ipv6, addr_ipv4); |
| if ((*newaddr = calloc(1, INET_ADDRSTRLEN)) == NULL) { |
| (void) fprintf(stderr, |
| gettext("out of memory\n")); |
| exit(1); |
| } |
| if (inet_ntop(AF_INET, &addr_ipv4, *newaddr, |
| INET_ADDRSTRLEN)) |
| return (AF_INET6); |
| free(*newaddr); |
| return (-2); |
| } |
| |
| /* Processing general IPv6 addresses */ |
| if ((*newaddr = calloc(1, INET6_ADDRSTRLEN)) == NULL) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| if (inet_ntop(AF_INET6, &addr_ipv6, *newaddr, INET6_ADDRSTRLEN)) |
| return (AF_INET6); |
| free(*newaddr); |
| return (-2); |
| } |
| |
| /* Processing IPv4 addresses of the type d.d.d.d. */ |
| if (inet_pton(AF_INET, addr, &addr_ipv4) == 1) { |
| if (newaddr == NULL) |
| return (AF_INET); |
| if ((*newaddr = calloc(1, INET_ADDRSTRLEN)) == NULL) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| if (inet_ntop(AF_INET, &addr_ipv4, *newaddr, INET_ADDRSTRLEN)) |
| return (AF_INET); |
| free(*newaddr); |
| return (-2); |
| } |
| |
| /* Processing IPv4 addresses d.d.d , d.d and d */ |
| if (inet_addr(addr) != (in_addr_t)-1) { |
| if (newaddr == NULL) |
| return (AF_INET); |
| if ((*newaddr = strdup(addr)) == NULL) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| return (AF_INET); |
| } |
| |
| return (-1); |
| } |
| |
| static int |
| genent_hosts(char *line, int (*cback)()) |
| { |
| char buf[BUFSIZ+1]; |
| char *t; |
| entry_col ecol[4]; |
| char *cname, *pref_addr; |
| int ctr = 0, retval = 1; |
| int rc = GENENT_OK, af; |
| |
| struct hostent data; |
| char *alias; |
| |
| /* |
| * don't clobber our argument |
| */ |
| if (strlen(line) >= sizeof (buf)) { |
| (void) strcpy(parse_err_msg, "line too long"); |
| return (GENENT_PARSEERR); |
| } |
| (void) strcpy(buf, line); |
| |
| /* |
| * clear column data |
| */ |
| (void) memset((char *)ecol, 0, sizeof (ecol)); |
| |
| /* |
| * comment (col 3) |
| */ |
| t = strchr(buf, '#'); |
| if (t) { |
| *t++ = 0; |
| ecol[3].ec_value.ec_value_val = t; |
| ecol[3].ec_value.ec_value_len = strlen(t)+1; |
| } else { |
| ecol[3].ec_value.ec_value_val = ""; |
| ecol[3].ec_value.ec_value_len = 0; |
| } |
| |
| |
| /* |
| * addr(col 2) |
| */ |
| if ((t = strtok(buf, " \t")) == 0) { |
| (void) strcpy(parse_err_msg, "no host"); |
| return (GENENT_PARSEERR); |
| } |
| |
| af = check_ipaddr(t, &pref_addr); |
| if (af == -2) { |
| (void) strcpy(parse_err_msg, "Internal error"); |
| } else if (af == -1) { |
| (void) snprintf(parse_err_msg, sizeof (parse_err_msg), |
| "Invalid IP address: %s", t); |
| } else if (flags & F_VERBOSE) { |
| if ((strncasecmp(t, pref_addr, strlen(t))) != 0) { |
| (void) fprintf(stdout, |
| gettext("IP address %s converted to %s\n"), |
| t, pref_addr); |
| } |
| } |
| |
| if (af < 0) { |
| (void) fprintf(stderr, gettext("%s\n"), parse_err_msg); |
| if (continue_onerror == 0) |
| return (GENENT_CBERR); |
| else |
| return (rc); |
| } |
| |
| ecol[2].ec_value.ec_value_val = pref_addr; |
| ecol[2].ec_value.ec_value_len = strlen(pref_addr)+1; |
| |
| /* |
| * cname (col 0) |
| */ |
| if ((t = strtok(NULL, " \t")) == 0) { |
| (void) strcpy(parse_err_msg, "no cname"); |
| return (GENENT_PARSEERR); |
| } |
| ecol[0].ec_value.ec_value_val = t; |
| ecol[0].ec_value.ec_value_len = strlen(t)+1; |
| cname = t; |
| |
| |
| /* build entry */ |
| if ((data.h_addr_list = (char **)calloc(2, sizeof (char **))) == NULL) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| data.h_addr_list[0] = strdup(ecol[2].ec_value.ec_value_val); |
| data.h_addr_list[1] = NULL; |
| |
| free(pref_addr); |
| data.h_name = strdup(ecol[0].ec_value.ec_value_val); |
| |
| /* |
| * name (col 1) |
| */ |
| |
| data.h_aliases = NULL; |
| |
| do { |
| /* |
| * don't clobber comment in canonical entry |
| */ |
| |
| /* This call to AddEntry may move out of the loop */ |
| /* This is because we have to call the function just once */ |
| if (t != cname && strcasecmp(t, cname) == 0) |
| continue; |
| if (strcasecmp(t, ecol[0].ec_value.ec_value_val) == 0) |
| continue; |
| |
| ecol[1].ec_value.ec_value_val = t; |
| ecol[1].ec_value.ec_value_len = strlen(t)+1; |
| |
| ctr++; |
| alias = strdup(ecol[1].ec_value.ec_value_val); |
| if ((data.h_aliases = (char **)realloc(data.h_aliases, |
| ctr * sizeof (char **))) == NULL) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| data.h_aliases[ctr-1] = alias; |
| |
| /* |
| * only put comment in canonical entry |
| */ |
| ecol[3].ec_value.ec_value_val = 0; |
| ecol[3].ec_value.ec_value_len = 0; |
| |
| } while (t = strtok(NULL, " \t")); |
| |
| /* End the list of all the aliases by NULL */ |
| if ((data.h_aliases = (char **)realloc(data.h_aliases, |
| (ctr + 1) * sizeof (char **))) == NULL) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| data.h_aliases[ctr] = NULL; |
| |
| if (flags & F_VERBOSE) |
| (void) fprintf(stdout, |
| gettext("Adding entry : cn=%s+ipHostNumber=%s\n"), |
| data.h_name, data.h_addr_list[0]); |
| |
| retval = (*cback)(&data, 0); |
| |
| if (retval == LDAP_ALREADY_EXISTS) { |
| if (continue_onerror) |
| (void) fprintf(stderr, |
| gettext("Entry: cn=%s+ipHostNumber=%s " |
| "already Exists -skipping it\n"), |
| data.h_name, data.h_addr_list[0]); |
| else { |
| rc = GENENT_CBERR; |
| (void) fprintf(stderr, |
| gettext("Entry: cn=%s+ipHostNumber=%s" |
| " already Exists\n"), |
| data.h_name, data.h_addr_list[0]); |
| } |
| } else if (retval) |
| rc = GENENT_CBERR; |
| |
| free(data.h_name); |
| free(data.h_aliases); |
| free(data.h_addr_list); |
| |
| return (rc); |
| } |
| |
| |
| |
| static void |
| dump_hosts(ns_ldap_result_t *res) |
| { |
| ns_ldap_attr_t *attrptr = NULL, *cn = NULL, *iphostnumber = NULL; |
| int i, j; |
| char *name; /* host name */ |
| |
| if (res == NULL || res->entry == NULL) |
| return; |
| for (i = 0; i < res->entry->attr_count; i++) { |
| attrptr = res->entry->attr_pair[i]; |
| if (strcasecmp(attrptr->attrname, "cn") == 0) |
| cn = attrptr; |
| else if (strcasecmp(attrptr->attrname, "iphostnumber") == 0) |
| iphostnumber = attrptr; |
| } |
| /* sanity check */ |
| if (cn == NULL || cn->attrvalue == NULL || cn->attrvalue[0] == NULL || |
| iphostnumber == NULL || iphostnumber->attrvalue == NULL || |
| iphostnumber->attrvalue[0] == NULL) |
| return; |
| |
| if ((name = __s_api_get_canonical_name(res->entry, cn, 1)) == NULL) |
| return; |
| |
| /* ip host/ipnode number */ |
| if (strlen(iphostnumber->attrvalue[0]) <= INET_ADDRSTRLEN) |
| /* IPV4 or IPV6 but <= NET_ADDRSTRLEN */ |
| (void) fprintf(stdout, "%-18s", iphostnumber->attrvalue[0]); |
| else |
| /* IPV6 */ |
| (void) fprintf(stdout, "%-48s", iphostnumber->attrvalue[0]); |
| |
| /* host/ipnode name */ |
| (void) fprintf(stdout, "%s ", name); |
| |
| /* aliases */ |
| for (j = 0; j < cn->value_count; j++) { |
| if (cn->attrvalue[j]) { |
| if (strcasecmp(name, cn->attrvalue[j]) == 0) |
| /* skip host name */ |
| continue; |
| (void) fprintf(stdout, "%s ", cn->attrvalue[j]); |
| } |
| } |
| |
| /* end of line */ |
| (void) fprintf(stdout, "\n"); |
| } |
| |
| /* |
| * /etc/rpc |
| */ |
| |
| static int |
| genent_rpc(char *line, int (*cback)()) |
| { |
| char buf[BUFSIZ+1]; |
| char *t; |
| entry_col ecol[4]; |
| char *cname; |
| |
| struct rpcent data; |
| char *alias; |
| int ctr = 0; |
| int retval = 1; |
| int rc = GENENT_OK; |
| |
| /* |
| * don't clobber our argument |
| */ |
| if (strlen(line) >= sizeof (buf)) { |
| (void) strcpy(parse_err_msg, "line too long"); |
| return (GENENT_PARSEERR); |
| } |
| (void) strcpy(buf, line); |
| |
| /* |
| * clear column data |
| */ |
| (void) memset((char *)ecol, 0, sizeof (ecol)); |
| |
| /* |
| * comment (col 3) |
| */ |
| t = strchr(buf, '#'); |
| if (t) { |
| *t++ = 0; |
| ecol[3].ec_value.ec_value_val = t; |
| ecol[3].ec_value.ec_value_len = strlen(t)+1; |
| } else { |
| ecol[3].ec_value.ec_value_val = 0; |
| ecol[3].ec_value.ec_value_len = 0; |
| } |
| |
| /* |
| * cname(col 0) |
| */ |
| if ((t = strtok(buf, " \t")) == 0) { |
| (void) strcpy(parse_err_msg, "no number"); |
| return (GENENT_PARSEERR); |
| } |
| ecol[0].ec_value.ec_value_val = t; |
| ecol[0].ec_value.ec_value_len = strlen(t)+1; |
| cname = t; |
| |
| /* |
| * number (col 2) |
| */ |
| if ((t = strtok(NULL, " \t")) == 0) { |
| (void) strcpy(parse_err_msg, "no number"); |
| return (GENENT_PARSEERR); |
| } |
| ecol[2].ec_value.ec_value_val = t; |
| ecol[2].ec_value.ec_value_len = strlen(t)+1; |
| |
| |
| /* |
| * build entry |
| */ |
| |
| data.r_name = strdup(ecol[0].ec_value.ec_value_val); |
| if (ecol[2].ec_value.ec_value_val != NULL && |
| ecol[2].ec_value.ec_value_val[0] != '\0') { |
| |
| data.r_number = ascii_to_int(ecol[2].ec_value.ec_value_val); |
| if (data.r_number == -1) { |
| (void) snprintf(parse_err_msg, sizeof (parse_err_msg), |
| "invalid program number: %s", |
| ecol[2].ec_value.ec_value_val); |
| return (GENENT_PARSEERR); |
| } |
| } else |
| data.r_number = -1; |
| |
| /* |
| * name (col 1) |
| */ |
| t = cname; |
| data.r_aliases = NULL; |
| do { |
| |
| /* |
| * don't clobber comment in canonical entry |
| */ |
| if (t != cname && strcasecmp(t, cname) == 0) |
| continue; |
| if (strcasecmp(t, ecol[0].ec_value.ec_value_val) == 0) |
| continue; |
| |
| ecol[1].ec_value.ec_value_val = t; |
| ecol[1].ec_value.ec_value_len = strlen(t)+1; |
| |
| ctr++; |
| alias = strdup(ecol[1].ec_value.ec_value_val); |
| if ((data.r_aliases = (char **)realloc(data.r_aliases, |
| ctr * sizeof (char **))) == NULL) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| data.r_aliases[ctr-1] = alias; |
| |
| |
| /* |
| * only put comment in canonical entry |
| */ |
| ecol[3].ec_value.ec_value_val = 0; |
| ecol[3].ec_value.ec_value_len = 0; |
| |
| } while (t = strtok(NULL, " \t")); |
| |
| /* End the list of all the aliases by NULL */ |
| if ((data.r_aliases = (char **)realloc(data.r_aliases, |
| (ctr + 1) * sizeof (char **))) == NULL) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| data.r_aliases[ctr] = NULL; |
| |
| if (flags & F_VERBOSE) |
| (void) fprintf(stdout, |
| gettext("Adding entry : %s\n"), data.r_name); |
| |
| retval = (*cback)(&data, 0); |
| |
| if (retval == LDAP_ALREADY_EXISTS) { |
| if (continue_onerror) |
| (void) fprintf(stderr, |
| gettext("Entry: %s - already Exists, skipping it.\n"), |
| data.r_name); |
| else { |
| rc = GENENT_CBERR; |
| (void) fprintf(stderr, |
| gettext("Entry: %s - already Exists\n"), |
| data.r_name); |
| } |
| } else if (retval) |
| rc = GENENT_CBERR; |
| |
| free(data.r_name); |
| free(data.r_aliases); |
| |
| return (rc); |
| } |
| |
| |
| |
| static void |
| dump_rpc(ns_ldap_result_t *res) |
| { |
| ns_ldap_attr_t *attrptr = NULL, *cn = NULL, *rpcnumber = NULL; |
| int i, j; |
| char *name; /* rpc name */ |
| |
| if (res == NULL || res->entry == NULL) |
| return; |
| for (i = 0; i < res->entry->attr_count; i++) { |
| attrptr = res->entry->attr_pair[i]; |
| if (strcasecmp(attrptr->attrname, "cn") == 0) |
| cn = attrptr; |
| else if (strcasecmp(attrptr->attrname, "oncRpcNumber") == 0) |
| rpcnumber = attrptr; |
| } |
| /* sanity check */ |
| if (cn == NULL || cn->attrvalue == NULL || cn->attrvalue[0] == NULL || |
| rpcnumber == NULL || rpcnumber->attrvalue == NULL || |
| rpcnumber->attrvalue[0] == NULL) |
| return; |
| |
| if ((name = __s_api_get_canonical_name(res->entry, cn, 1)) == NULL) |
| return; |
| |
| /* rpc name */ |
| if (strlen(name) < 8) |
| (void) fprintf(stdout, "%s\t\t", name); |
| else |
| (void) fprintf(stdout, "%s\t", name); |
| |
| /* rpc number */ |
| (void) fprintf(stdout, "%-8s", rpcnumber->attrvalue[0]); |
| |
| |
| /* aliases */ |
| for (j = 0; j < cn->value_count; j++) { |
| if (cn->attrvalue[j]) { |
| if (strcasecmp(name, cn->attrvalue[j]) == 0) |
| /* skip rpc name */ |
| continue; |
| (void) fprintf(stdout, "%s ", cn->attrvalue[j]); |
| } |
| } |
| |
| /* end of line */ |
| (void) fprintf(stdout, "\n"); |
| |
| } |
| |
| /* |
| * /etc/protocols |
| * |
| */ |
| |
| static int |
| genent_protocols(char *line, int (*cback)()) |
| { |
| char buf[BUFSIZ+1]; |
| char *t; |
| entry_col ecol[4]; |
| char *cname; |
| |
| struct protoent data; |
| char *alias; |
| int ctr = 0; |
| int retval = 1; |
| int rc = GENENT_OK; |
| |
| /* |
| * don't clobber our argument |
| */ |
| if (strlen(line) >= sizeof (buf)) { |
| (void) strcpy(parse_err_msg, "line too long"); |
| return (GENENT_PARSEERR); |
| } |
| (void) strcpy(buf, line); |
| |
| /* |
| * clear column data |
| */ |
| (void) memset((char *)ecol, 0, sizeof (ecol)); |
| |
| /* |
| * comment (col 3) |
| */ |
| t = strchr(buf, '#'); |
| if (t) { |
| *t++ = 0; |
| ecol[3].ec_value.ec_value_val = t; |
| ecol[3].ec_value.ec_value_len = strlen(t)+1; |
| } else { |
| ecol[3].ec_value.ec_value_val = 0; |
| ecol[3].ec_value.ec_value_len = 0; |
| } |
| |
| /* |
| * cname(col 0) |
| */ |
| if ((t = strtok(buf, " \t")) == 0) { |
| (void) strcpy(parse_err_msg, "no number"); |
| return (GENENT_PARSEERR); |
| } |
| ecol[0].ec_value.ec_value_val = t; |
| ecol[0].ec_value.ec_value_len = strlen(t)+1; |
| cname = t; |
| |
| /* |
| * number (col 2) |
| */ |
| if ((t = strtok(NULL, " \t")) == 0) { |
| (void) strcpy(parse_err_msg, "no number"); |
| return (GENENT_PARSEERR); |
| } |
| ecol[2].ec_value.ec_value_val = t; |
| ecol[2].ec_value.ec_value_len = strlen(t)+1; |
| |
| |
| /* |
| * build entry |
| */ |
| data.p_name = strdup(ecol[0].ec_value.ec_value_val); |
| |
| if (ecol[2].ec_value.ec_value_val != NULL && |
| ecol[2].ec_value.ec_value_val[0] != '\0') { |
| |
| data.p_proto = ascii_to_int(ecol[2].ec_value.ec_value_val); |
| if (data.p_proto == -1) { |
| (void) snprintf(parse_err_msg, sizeof (parse_err_msg), |
| "invalid protocol number: %s", |
| ecol[2].ec_value.ec_value_val); |
| return (GENENT_PARSEERR); |
| } |
| } else |
| data.p_proto = -1; |
| |
| /* |
| * name (col 1) |
| */ |
| t = cname; |
| ctr = 0; |
| data.p_aliases = NULL; |
| |
| do { |
| /* |
| * don't clobber comment in canonical entry |
| */ |
| if (t != cname && strcasecmp(t, cname) == 0) |
| continue; |
| if (strcasecmp(t, ecol[0].ec_value.ec_value_val) == 0) |
| continue; |
| |
| ecol[1].ec_value.ec_value_val = t; |
| ecol[1].ec_value.ec_value_len = strlen(t)+1; |
| |
| ctr++; |
| alias = strdup(ecol[1].ec_value.ec_value_val); |
| if ((data.p_aliases = (char **)realloc(data.p_aliases, |
| ctr * sizeof (char **))) == NULL) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| data.p_aliases[ctr-1] = alias; |
| |
| /* |
| * only put comment in canonical entry |
| */ |
| ecol[3].ec_value.ec_value_val = 0; |
| ecol[3].ec_value.ec_value_len = 0; |
| |
| } while (t = strtok(NULL, " \t")); |
| |
| /* End the list of all the aliases by NULL */ |
| if ((data.p_aliases = (char **)realloc(data.p_aliases, |
| (ctr + 1) * sizeof (char **))) == NULL) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| data.p_aliases[ctr] = NULL; |
| |
| if (flags & F_VERBOSE) |
| (void) fprintf(stdout, |
| gettext("Adding entry : %s\n"), data.p_name); |
| |
| retval = (*cback)(&data, 0); |
| |
| if (retval == LDAP_ALREADY_EXISTS) { |
| if (continue_onerror) |
| (void) fprintf(stderr, |
| gettext("Entry: %s - already Exists, skipping it.\n"), |
| data.p_name); |
| else { |
| rc = GENENT_CBERR; |
| (void) fprintf(stderr, |
| gettext("Entry: %s - already Exists\n"), |
| data.p_name); |
| } |
| } else if (retval) |
| rc = GENENT_CBERR; |
| |
| free(data.p_name); |
| free(data.p_aliases); |
| |
| return (rc); |
| } |
| |
| |
| static void |
| dump_protocols(ns_ldap_result_t *res) |
| { |
| ns_ldap_attr_t *attrptr = NULL, *cn = NULL, *protocolnumber = NULL; |
| int i, j; |
| char *name, *cp; |
| |
| if (res == NULL || res->entry == NULL) |
| return; |
| for (i = 0; i < res->entry->attr_count; i++) { |
| attrptr = res->entry->attr_pair[i]; |
| if (strcasecmp(attrptr->attrname, "cn") == 0) |
| cn = attrptr; |
| else if (strcasecmp(attrptr->attrname, "ipProtocolNumber") |
| == 0) |
| protocolnumber = attrptr; |
| } |
| /* sanity check */ |
| if (cn == NULL || cn->attrvalue == NULL || cn->attrvalue[0] == NULL || |
| protocolnumber == NULL || protocolnumber->attrvalue == NULL || |
| protocolnumber->attrvalue[0] == NULL) |
| return; |
| |
| if ((name = __s_api_get_canonical_name(res->entry, cn, 1)) == NULL) |
| return; |
| |
| /* protocol name */ |
| if (strlen(name) < 8) |
| (void) fprintf(stdout, "%s\t\t", name); |
| else |
| (void) fprintf(stdout, "%s\t", name); |
| |
| /* protocol number */ |
| (void) fprintf(stdout, "%-16s", protocolnumber->attrvalue[0]); |
| |
| /* aliases */ |
| for (j = 0; j < cn->value_count; j++) { |
| if (cn->attrvalue[j]) { |
| if (strcasecmp(name, cn->attrvalue[j]) == 0) { |
| if (cn->value_count > 1) |
| /* Do not replicate */ |
| continue; |
| /* |
| * Replicate name in uppercase as an aliase |
| */ |
| for (cp = cn->attrvalue[j]; *cp; cp++) |
| *cp = toupper(*cp); |
| } |
| (void) fprintf(stdout, "%s ", cn->attrvalue[j]); |
| } |
| } |
| |
| /* end of line */ |
| (void) fprintf(stdout, "\n"); |
| |
| } |
| |
| |
| |
| |
| |
| /* |
| * /etc/networks |
| * |
| */ |
| |
| static int |
| genent_networks(char *line, int (*cback)()) |
| { |
| char buf[BUFSIZ+1]; |
| char *t; |
| entry_col ecol[4]; |
| char *cname; |
| |
| struct netent data; |
| char *alias; |
| int ctr = 0; |
| int retval = 1; |
| int enet; |
| int rc = GENENT_OK; |
| |
| /* |
| * don't clobber our argument |
| */ |
| if (strlen(line) >= sizeof (buf)) { |
| (void) strcpy(parse_err_msg, "line too long"); |
| return (GENENT_PARSEERR); |
| } |
| (void) strcpy(buf, line); |
| |
| /* |
| * clear column data |
| */ |
| (void) memset((char *)ecol, 0, sizeof (ecol)); |
| |
| /* |
| * comment (col 3) |
| */ |
| t = strchr(buf, '#'); |
| if (t) { |
| *t++ = 0; |
| ecol[3].ec_value.ec_value_val = t; |
| ecol[3].ec_value.ec_value_len = strlen(t)+1; |
| } else { |
| ecol[3].ec_value.ec_value_val = 0; |
| ecol[3].ec_value.ec_value_len = 0; |
| } |
| |
| /* |
| * cname(col 0) |
| */ |
| if ((t = strtok(buf, " \t")) == 0) { |
| (void) strcpy(parse_err_msg, "no number"); |
| return (GENENT_PARSEERR); |
| } |
| ecol[0].ec_value.ec_value_val = t; |
| ecol[0].ec_value.ec_value_len = strlen(t)+1; |
| cname = t; |
| |
| /* |
| * number (col 2) |
| */ |
| if ((t = strtok(NULL, " \t")) == 0) { |
| (void) strcpy(parse_err_msg, "no number"); |
| return (GENENT_PARSEERR); |
| } |
| ecol[2].ec_value.ec_value_val = t; |
| ecol[2].ec_value.ec_value_len = strlen(t)+1; |
| |
| |
| /* |
| * build entry |
| */ |
| |
| data.n_name = strdup(ecol[0].ec_value.ec_value_val); |
| /* |
| * data.n_net is an unsigned field, |
| * assign -1 to it, make no sense. |
| * Use enet here to avoid lint warning. |
| */ |
| enet = encode_network(ecol[2].ec_value.ec_value_val); |
| |
| if (enet == -1 && continue_onerror == 0) { |
| (void) fprintf(stderr, gettext("Invalid network number\n")); |
| if (continue_onerror == 0) |
| return (GENENT_CBERR); |
| } else |
| data.n_net = enet; |
| |
| /* |
| * name (col 1) |
| */ |
| t = cname; |
| data.n_aliases = NULL; |
| |
| do { |
| /* |
| * don't clobber comment in canonical entry |
| */ |
| if (t != cname && strcasecmp(t, cname) == 0) |
| continue; |
| if (strcasecmp(t, ecol[0].ec_value.ec_value_val) == 0) |
| continue; |
| |
| ecol[1].ec_value.ec_value_val = t; |
| ecol[1].ec_value.ec_value_len = strlen(t)+1; |
| |
| ctr++; |
| alias = strdup(ecol[1].ec_value.ec_value_val); |
| if ((data.n_aliases = (char **)realloc(data.n_aliases, |
| ctr * sizeof (char **))) == NULL) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| data.n_aliases[ctr-1] = alias; |
| |
| /* |
| * only put comment in canonical entry |
| */ |
| ecol[3].ec_value.ec_value_val = 0; |
| ecol[3].ec_value.ec_value_len = 0; |
| |
| } while (t = strtok(NULL, " \t")); |
| |
| /* End the list of all the aliases by NULL */ |
| if ((data.n_aliases = (char **)realloc(data.n_aliases, |
| (ctr + 1) * sizeof (char **))) == NULL) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| data.n_aliases[ctr] = NULL; |
| |
| if (flags & F_VERBOSE) |
| (void) fprintf(stdout, |
| gettext("Adding entry : %s\n"), data.n_name); |
| |
| retval = (*cback)(&data, 0); |
| |
| if (retval == LDAP_ALREADY_EXISTS) { |
| if (continue_onerror) |
| (void) fprintf(stderr, |
| gettext("Entry: %s - already Exists, skipping it.\n"), |
| data.n_name); |
| else { |
| rc = GENENT_CBERR; |
| (void) fprintf(stderr, |
| gettext("Entry: %s - already Exists\n"), |
| data.n_name); |
| } |
| } else if (retval) |
| rc = GENENT_CBERR; |
| |
| free(data.n_name); |
| free(data.n_aliases); |
| |
| return (rc); |
| } |
| |
| |
| static void |
| dump_networks(ns_ldap_result_t *res) |
| { |
| ns_ldap_attr_t *attrptr = NULL, *cn = NULL, *networknumber = NULL; |
| int i, j; |
| char *name; |
| |
| if (res == NULL || res->entry == NULL) |
| return; |
| for (i = 0; i < res->entry->attr_count; i++) { |
| attrptr = res->entry->attr_pair[i]; |
| if (strcasecmp(attrptr->attrname, "cn") == 0) |
| cn = attrptr; |
| else if (strcasecmp(attrptr->attrname, "ipNetworkNumber") |
| == 0) |
| networknumber = attrptr; |
| } |
| /* sanity check */ |
| if (cn == NULL || cn->attrvalue == NULL || cn->attrvalue[0] == NULL || |
| networknumber == NULL || networknumber->attrvalue == NULL || |
| networknumber->attrvalue[0] == NULL) |
| return; |
| |
| /* |
| * cn can be a MUST attribute(RFC 2307) or MAY attribute(2307bis). |
| * If the canonical name can not be found (2307bis), use the 1st |
| * value as the official name. |
| */ |
| |
| /* network name */ |
| if ((name = __s_api_get_canonical_name(res->entry, cn, 1)) == NULL) |
| name = cn->attrvalue[0]; |
| |
| if (strlen(name) < 8) |
| (void) fprintf(stdout, "%s\t\t", name); |
| else |
| (void) fprintf(stdout, "%s\t", name); |
| |
| /* network number */ |
| (void) fprintf(stdout, "%-16s", networknumber->attrvalue[0]); |
| |
| /* aliases */ |
| for (j = 0; j < cn->value_count; j++) { |
| if (cn->attrvalue[j]) { |
| if (strcasecmp(name, cn->attrvalue[j]) == 0) |
| /* skip name */ |
| continue; |
| (void) fprintf(stdout, "%s ", cn->attrvalue[j]); |
| } |
| } |
| |
| /* end of line */ |
| (void) fprintf(stdout, "\n"); |
| |
| } |
| |
| |
| |
| |
| /* |
| * /etc/services |
| * |
| */ |
| |
| static int |
| genent_services(char *line, int (*cback)()) |
| { |
| char buf[BUFSIZ+1]; |
| char *t, *p; |
| entry_col ecol[5]; |
| char *cname; |
| |
| struct servent data; |
| char *alias; |
| int ctr = 0; |
| int retval = 1; |
| int rc = GENENT_OK; |
| |
| /* |
| * don't clobber our argument |
| */ |
| if (strlen(line) >= sizeof (buf)) { |
| (void) strcpy(parse_err_msg, "line too long"); |
| return (GENENT_PARSEERR); |
| } |
| (void) strcpy(buf, line); |
| |
| /* |
| * clear column data |
| */ |
| (void) memset((char *)ecol, 0, sizeof (ecol)); |
| |
| /* |
| * comment (col 4) |
| */ |
| t = strchr(buf, '#'); |
| if (t) { |
| *t++ = 0; |
| ecol[4].ec_value.ec_value_val = t; |
| ecol[4].ec_value.ec_value_len = strlen(t)+1; |
| } else { |
| ecol[4].ec_value.ec_value_val = 0; |
| ecol[4].ec_value.ec_value_len = 0; |
| } |
| |
| /* |
| * cname(col 0) |
| */ |
| if ((t = strtok(buf, " \t")) == 0) { |
| (void) strcpy(parse_err_msg, "no port"); |
| return (GENENT_PARSEERR); |
| } |
| ecol[0].ec_value.ec_value_val = t; |
| ecol[0].ec_value.ec_value_len = strlen(t)+1; |
| cname = t; |
| |
| /* |
| * port (col 3) |
| */ |
| if ((t = strtok(NULL, " \t")) == 0) { |
| (void) strcpy(parse_err_msg, "no protocol"); |
| return (GENENT_PARSEERR); |
| } |
| if ((p = strchr(t, '/')) == 0) { |
| (void) strcpy(parse_err_msg, "bad port/proto"); |
| return (GENENT_PARSEERR); |
| } |
| *(p++) = 0; |
| ecol[3].ec_value.ec_value_val = t; |
| ecol[3].ec_value.ec_value_len = strlen(t)+1; |
| |
| /* |
| * proto (col 2) |
| */ |
| ecol[2].ec_value.ec_value_val = p; |
| ecol[2].ec_value.ec_value_len = strlen(p)+1; |
| |
| |
| /* |
| * build entry |
| */ |
| |
| data.s_name = strdup(ecol[0].ec_value.ec_value_val); |
| data.s_proto = strdup(ecol[2].ec_value.ec_value_val); |
| |
| if (ecol[3].ec_value.ec_value_val != NULL && |
| ecol[3].ec_value.ec_value_val[0] != '\0') { |
| |
| data.s_port = ascii_to_int(ecol[3].ec_value.ec_value_val); |
| if (data.s_port == -1) { |
| (void) snprintf(parse_err_msg, sizeof (parse_err_msg), |
| "invalid port number: %s", |
| ecol[3].ec_value.ec_value_val); |
| return (GENENT_PARSEERR); |
| } |
| } else |
| data.s_port = -1; |
| |
| /* |
| * name (col 1) |
| */ |
| t = cname; |
| data.s_aliases = NULL; |
| |
| do { |
| /* |
| * don't clobber comment in canonical entry |
| */ |
| if (t != cname && strcasecmp(t, cname) == 0) |
| continue; |
| if (strcasecmp(t, ecol[0].ec_value.ec_value_val) == 0) |
| continue; |
| |
| ecol[1].ec_value.ec_value_val = t; |
| ecol[1].ec_value.ec_value_len = strlen(t)+1; |
| |
| ctr++; |
| alias = strdup(ecol[1].ec_value.ec_value_val); |
| if ((data.s_aliases = (char **)realloc(data.s_aliases, |
| ctr * sizeof (char **))) == NULL) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| data.s_aliases[ctr-1] = alias; |
| |
| /* |
| * only put comment in canonical entry |
| */ |
| ecol[4].ec_value.ec_value_val = 0; |
| ecol[4].ec_value.ec_value_len = 0; |
| |
| } while (t = strtok(NULL, " \t")); |
| |
| /* End the list of all the aliases by NULL */ |
| if ((data.s_aliases = (char **)realloc(data.s_aliases, |
| (ctr + 1) * sizeof (char **))) == NULL) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| data.s_aliases[ctr] = NULL; |
| |
| if (flags & F_VERBOSE) |
| (void) fprintf(stdout, |
| gettext("Adding entry : %s\n"), line); |
| |
| retval = (*cback)(&data, 0); |
| |
| if (retval == LDAP_ALREADY_EXISTS) { |
| if (continue_onerror) |
| (void) fprintf(stderr, gettext( |
| "Entry: cn=%s+ipServiceProtocol=%s" |
| " already Exists, skipping it.\n"), |
| data.s_name, data.s_proto); |
| else { |
| rc = GENENT_CBERR; |
| (void) fprintf(stderr, |
| gettext("Entry: cn=%s+ipServiceProtocol=%s" |
| " - already Exists\n"), |
| data.s_name, data.s_proto); |
| } |
| } else if (retval) |
| rc = GENENT_CBERR; |
| |
| free(data.s_name); |
| free(data.s_proto); |
| free(data.s_aliases); |
| |
| return (rc); |
| } |
| |
| |
| |
| static void |
| dump_services(ns_ldap_result_t *res) |
| { |
| ns_ldap_attr_t *attrptr = NULL, *cn = NULL, *port = NULL; |
| ns_ldap_attr_t *protocol = NULL; |
| int i, j, len; |
| char *name; /* service name */ |
| |
| /* |
| * cn can have multiple values.(service name and its aliases) |
| * In order to support RFC 2307, section 5.5, ipserviceprotocol can |
| * have multiple values too. |
| * The output format should look like |
| * |
| * test 2345/udp mytest |
| * test 2345/tcp mytest |
| */ |
| if (res == NULL || res->entry == NULL) |
| return; |
| for (i = 0; i < res->entry->attr_count; i++) { |
| attrptr = res->entry->attr_pair[i]; |
| if (strcasecmp(attrptr->attrname, "cn") == 0) |
| cn = attrptr; |
| else if (strcasecmp(attrptr->attrname, "ipServicePort") == 0) |
| port = attrptr; |
| else if (strcasecmp(attrptr->attrname, |
| "ipServiceProtocol") == 0) |
| protocol = attrptr; |
| } |
| /* sanity check */ |
| if (cn == NULL || cn->attrvalue == NULL || cn->attrvalue[0] == NULL || |
| port == NULL || port->attrvalue == NULL || |
| port->attrvalue[0] == NULL || protocol == NULL || |
| protocol->attrvalue == NULL || protocol->attrvalue[0] == NULL) |
| return; |
| |
| if ((name = __s_api_get_canonical_name(res->entry, cn, 1)) == NULL) |
| return; |
| for (i = 0; i < protocol->value_count; i++) { |
| if (protocol->attrvalue[i] == NULL) |
| return; |
| /* service name */ |
| (void) fprintf(stdout, "%-16s", name); |
| |
| /* port & protocol */ |
| (void) fprintf(stdout, "%s/%s%n", port->attrvalue[0], |
| protocol->attrvalue[i], &len); |
| |
| if (len < 8) |
| (void) fprintf(stdout, "\t\t"); |
| else |
| (void) fprintf(stdout, "\t"); |
| |
| /* aliases */ |
| for (j = 0; j < cn->value_count; j++) { |
| if (cn->attrvalue[j]) { |
| if (strcasecmp(name, cn->attrvalue[j]) == 0) |
| /* skip service name */ |
| continue; |
| (void) fprintf(stdout, "%s ", cn->attrvalue[j]); |
| } |
| } |
| |
| /* end of line */ |
| (void) fprintf(stdout, "\n"); |
| } |
| } |
| |
| |
| /* |
| * /etc/group |
| */ |
| |
| static int |
| genent_group(char *line, int (*cback)()) |
| { |
| char buf[BIGBUF+1]; |
| char *s, *t; |
| entry_col ecol[5]; |
| |
| struct group data; |
| int ctr = 0; |
| int retval = 1; |
| int rc = GENENT_OK; |
| |
| /* |
| * don't clobber our argument |
| */ |
| if (strlen(line) >= sizeof (buf)) { |
| (void) strcpy(parse_err_msg, "line too long"); |
| return (GENENT_PARSEERR); |
| } |
| (void) strcpy(buf, line); |
| t = buf; |
| |
| /* ignore empty entries */ |
| if (*t == '\0') |
| return (GENENT_OK); |
| |
| /* |
| * clear column data |
| */ |
| (void) memset((char *)ecol, 0, sizeof (ecol)); |
| |
| /* |
| * name (col 0) |
| */ |
| if ((s = strchr(t, ':')) == 0) { |
| (void) strcpy(parse_err_msg, "no passwd"); |
| return (GENENT_PARSEERR); |
| } |
| *s++ = 0; |
| ecol[0].ec_value.ec_value_val = t; |
| ecol[0].ec_value.ec_value_len = strlen(t)+1; |
| t = s; |
| |
| /* |
| * passwd (col 1) |
| */ |
| if ((s = strchr(t, ':')) == 0) { |
| (void) strcpy(parse_err_msg, "no gid"); |
| return (GENENT_PARSEERR); |
| } |
| *s++ = 0; |
| ecol[1].ec_value.ec_value_val = t; |
| ecol[1].ec_value.ec_value_len = strlen(t)+1; |
| t = s; |
| |
| |
| /* |
| * gid (col 2) |
| */ |
| if ((s = strchr(t, ':')) == 0 || s == t) { |
| (void) strcpy(parse_err_msg, "no members"); |
| return (GENENT_PARSEERR); |
| } |
| *s++ = 0; |
| ecol[2].ec_value.ec_value_val = t; |
| ecol[2].ec_value.ec_value_len = strlen(t)+1; |
| t = s; |
| |
| /* |
| * members (col 3) |
| */ |
| ecol[3].ec_value.ec_value_val = t; |
| ecol[3].ec_value.ec_value_len = strlen(t)+1; |
| |
| |
| /* |
| * build entry |
| */ |
| data.gr_name = strdup(ecol[0].ec_value.ec_value_val); |
| data.gr_passwd = strdup(ecol[1].ec_value.ec_value_val); |
| if (ecol[2].ec_value.ec_value_val != NULL && |
| ecol[2].ec_value.ec_value_val[0] != '\0') { |
| |
| data.gr_gid = ascii_to_int(ecol[2].ec_value.ec_value_val); |
| if (data.gr_gid == -1) { |
| (void) snprintf(parse_err_msg, sizeof (parse_err_msg), |
| "invalid group id: %s", |
| ecol[2].ec_value.ec_value_val); |
| return (GENENT_PARSEERR); |
| } |
| } else |
| data.gr_gid = -1; |
| |
| data.gr_mem = NULL; |
| |
| /* Compute maximum amount of members */ |
| s = t; |
| while (s = strchr(s, ',')) { |
| s++; |
| ctr++; |
| } |
| |
| /* Allocate memory for all members */ |
| data.gr_mem = calloc(ctr + 2, sizeof (char **)); |
| if (data.gr_mem == NULL) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| |
| ctr = 0; |
| while (s = strchr(t, ',')) { |
| |
| *s++ = 0; |
| ecol[3].ec_value.ec_value_val = t; |
| t = s; |
| /* Send to server only non empty member names */ |
| if (strlen(ecol[3].ec_value.ec_value_val) != 0) |
| data.gr_mem[ctr++] = ecol[3].ec_value.ec_value_val; |
| } |
| |
| /* Send to server only non empty member names */ |
| if (strlen(t) != 0) |
| data.gr_mem[ctr++] = t; |
| |
| /* Array of members completed, finished by NULL, see calloc() */ |
| |
| if (flags & F_VERBOSE) |
| (void) fprintf(stdout, |
| gettext("Adding entry : %s\n"), data.gr_name); |
| |
| retval = (*cback)(&data, 0); |
| |
| if (retval == LDAP_ALREADY_EXISTS) { |
| if (continue_onerror) |
| (void) fprintf(stderr, |
| gettext("Entry: %s - already Exists, skipping it.\n"), |
| data.gr_name); |
| else { |
| rc = GENENT_CBERR; |
| (void) fprintf(stderr, |
| gettext("Entry: %s - already Exists\n"), |
| data.gr_name); |
| } |
| } else if (retval) |
| rc = GENENT_CBERR; |
| |
| free(data.gr_name); |
| free(data.gr_passwd); |
| free(data.gr_mem); |
| |
| return (rc); |
| } |
| |
| static void |
| dump_group(ns_ldap_result_t *res) |
| { |
| char **value = NULL; |
| char pnam[256]; |
| int attr_count = 0; |
| |
| value = __ns_ldap_getAttr(res->entry, "cn"); |
| if (value && value[0]) |
| (void) fprintf(stdout, "%s:", value[0]); |
| value = __ns_ldap_getAttr(res->entry, "userPassword"); |
| if (value == NULL || value[0] == NULL) |
| (void) fprintf(stdout, "*:"); |
| else { |
| (void) strcpy(pnam, value[0]); |
| if (strncasecmp(value[0], "{crypt}", 7) == 0) |
| (void) fprintf(stdout, "%s:", (pnam+7)); |
| else |
| (void) fprintf(stdout, "*:"); |
| } |
| value = __ns_ldap_getAttr(res->entry, "gidNumber"); |
| if (value && value[0]) |
| (void) fprintf(stdout, "%s:", value[0]); |
| |
| value = __ns_ldap_getAttr(res->entry, "memberUid"); |
| if (value != NULL && value[0] != NULL) { |
| while (value[attr_count] != NULL) { |
| if (value[attr_count+1] == NULL) |
| (void) fprintf(stdout, "%s", value[attr_count]); |
| else |
| (void) fprintf(stdout, "%s,", |
| value[attr_count]); |
| attr_count++; |
| } |
| (void) fprintf(stdout, "\n"); |
| } |
| else |
| (void) fprintf(stdout, "\n"); |
| } |
| |
| |
| |
| |
| |
| /* |
| * /etc/ethers |
| */ |
| |
| static int |
| genent_ethers(char *line, int (*cback)()) |
| { |
| char buf[BUFSIZ+1]; |
| char *t; |
| entry_col ecol[3]; |
| int retval = 1; |
| struct _ns_ethers data; |
| int rc = GENENT_OK; |
| |
| /* |
| * don't clobber our argument |
| */ |
| if (strlen(line) >= sizeof (buf)) { |
| (void) strcpy(parse_err_msg, "line too long"); |
| return (GENENT_PARSEERR); |
| } |
| (void) strcpy(buf, line); |
| |
| /* |
| * clear column data |
| */ |
| (void) memset((char *)ecol, 0, sizeof (ecol)); |
| |
| /* |
| * comment (col 2) |
| */ |
| t = strchr(buf, '#'); |
| if (t) { |
| *t++ = 0; |
| ecol[2].ec_value.ec_value_val = t; |
| ecol[2].ec_value.ec_value_len = strlen(t)+1; |
| } else { |
| ecol[2].ec_value.ec_value_val = 0; |
| ecol[2].ec_value.ec_value_len = 0; |
| } |
| |
| /* |
| * addr(col 0) |
| */ |
| if ((t = strtok(buf, " \t")) == 0) { |
| (void) strcpy(parse_err_msg, "no name"); |
| return (GENENT_PARSEERR); |
| } |
| ecol[0].ec_value.ec_value_val = t; |
| ecol[0].ec_value.ec_value_len = strlen(t)+1; |
| |
| /* |
| * name(col 1) |
| */ |
| if ((t = strtok(NULL, " \t")) == 0) { |
| (void) strcpy(parse_err_msg, "no white space allowed in name"); |
| return (GENENT_PARSEERR); |
| } |
| ecol[1].ec_value.ec_value_val = t; |
| ecol[1].ec_value.ec_value_len = strlen(t)+1; |
| |
| |
| /* |
| * build entry |
| */ |
| |
| data.ether = strdup(ecol[0].ec_value.ec_value_val); |
| data.name = strdup(ecol[1].ec_value.ec_value_val); |
| |
| |
| if (flags & F_VERBOSE) |
| (void) fprintf(stdout, |
| gettext("Adding entry : %s\n"), data.name); |
| |
| retval = (*cback)(&data, 0); |
| |
| if (retval == LDAP_ALREADY_EXISTS) { |
| if (continue_onerror) |
| (void) fprintf(stderr, |
| gettext("Entry: %s - already Exists, skipping it.\n"), |
| data.name); |
| else { |
| rc = GENENT_CBERR; |
| (void) fprintf(stderr, |
| gettext("Entry: %s - already Exists\n"), |
| data.name); |
| } |
| } else if (retval) |
| rc = GENENT_CBERR; |
| |
| free(data.ether); |
| free(data.name); |
| |
| return (rc); |
| } |
| |
| |
| static void |
| dump_ethers(ns_ldap_result_t *res) |
| { |
| char **value = NULL; |
| |
| value = __ns_ldap_getAttr(res->entry, "macAddress"); |
| if (value && value[0]) |
| (void) fprintf(stdout, "%s", value[0]); |
| else |
| return; |
| value = __ns_ldap_getAttr(res->entry, "cn"); |
| if (value && value[0]) |
| (void) fprintf(stdout, " %s\n", value[0]); |
| } |
| |
| static int |
| genent_aliases(char *line, int (*cback)()) |
| { |
| char buf[BUFSIZ+1]; |
| char *t, *aliases; |
| char *cname; |
| int ctr = 0; |
| int retval = 1; |
| int i; |
| |
| struct _ns_alias data; |
| char *alias; |
| int rc = GENENT_OK; |
| |
| /* |
| * don't clobber our argument |
| */ |
| if (strlen(line) >= sizeof (buf)) { |
| (void) strcpy(parse_err_msg, "line too long"); |
| return (GENENT_PARSEERR); |
| } |
| |
| (void) strcpy(buf, line); |
| |
| if ((t = strchr(buf, ':')) == 0) { |
| (void) strcpy(parse_err_msg, "no alias name"); |
| return (GENENT_PARSEERR); |
| } |
| |
| t[0] = '\0'; |
| if (++t == '\0') { |
| (void) strcpy(parse_err_msg, "no alias value"); |
| return (GENENT_PARSEERR); |
| } |
| |
| cname = buf; |
| aliases = t; |
| |
| /* build entry */ |
| data.alias = strdup(cname); |
| if (!data.alias) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| |
| data.member = NULL; |
| t = strtok(aliases, ","); |
| do { |
| ctr++; |
| while (t[0] == ' ') |
| t++; |
| alias = strdup(t); |
| if ((alias == NULL) || |
| ((data.member = (char **)realloc(data.member, |
| (ctr + 1) * sizeof (char **))) == NULL)) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| data.member[ctr-1] = alias; |
| |
| } while (t = strtok(NULL, ",")); |
| |
| data.member[ctr] = NULL; |
| |
| if (flags & F_VERBOSE) |
| (void) fprintf(stdout, |
| gettext("Adding entry : %s\n"), data.alias); |
| |
| retval = (*cback)(&data, 0); |
| |
| if (retval == LDAP_ALREADY_EXISTS) { |
| if (continue_onerror) |
| (void) fprintf(stderr, |
| gettext("Entry: %s - already Exists, skipping it.\n"), |
| data.alias); |
| else { |
| rc = GENENT_CBERR; |
| (void) fprintf(stderr, |
| gettext("Entry: %s - already Exists\n"), |
| data.alias); |
| } |
| } else if (retval) |
| rc = GENENT_CBERR; |
| |
| free(data.alias); |
| i = 0; |
| while (data.member[i]) |
| free(data.member[i++]); |
| free(data.member); |
| |
| return (rc); |
| } |
| |
| |
| static void |
| dump_aliases(ns_ldap_result_t *res) |
| { |
| |
| char **value = NULL; |
| int attr_count = 0; |
| |
| value = __ns_ldap_getAttr(res->entry, "mail"); |
| if (value && value[0]) |
| (void) fprintf(stdout, "%s:", value[0]); |
| value = __ns_ldap_getAttr(res->entry, "mgrpRFC822MailMember"); |
| if (value != NULL) |
| while (value[attr_count] != NULL) { |
| (void) fprintf(stdout, "%s,", value[attr_count]); |
| attr_count++; |
| } |
| (void) fprintf(stdout, "\n"); |
| |
| } |
| |
| /* |
| * /etc/publickey |
| */ |
| |
| static int |
| genent_publickey(char *line, int (*cback)()) |
| { |
| char buf[BUFSIZ+1], tmpbuf[BUFSIZ+1], cname[BUFSIZ+1]; |
| char *t, *p, *tmppubkey, *tmpprivkey; |
| entry_col ecol[3]; |
| int buflen, uid, retval = 1; |
| struct passwd *pwd; |
| char auth_type[BUFSIZ+1]; |
| keylen_t keylen; |
| algtype_t algtype; |
| struct _ns_pubkey data; |
| struct hostent *hp; |
| struct in_addr in; |
| |
| /* |
| * don't clobber our argument |
| */ |
| if (strlen(line) >= sizeof (buf)) { |
| (void) strcpy(parse_err_msg, "line too long"); |
| return (GENENT_PARSEERR); |
| } |
| (void) strcpy(buf, line); |
| |
| /* |
| * clear column data |
| */ |
| (void) memset((char *)ecol, 0, sizeof (ecol)); |
| |
| if ((t = strtok(buf, " \t")) == 0) { |
| (void) strcpy(parse_err_msg, "no cname"); |
| return (GENENT_PARSEERR); |
| } |
| |
| /* |
| * Special case: /etc/publickey usually has an entry |
| * for principal "nobody". We skip it. |
| */ |
| if (strcmp(t, "nobody") == 0) |
| return (GENENT_OK); |
| |
| /* |
| * cname (col 0) |
| */ |
| if (strncmp(t, "unix.", 5)) { |
| (void) strcpy(parse_err_msg, "bad cname"); |
| return (GENENT_PARSEERR); |
| } |
| (void) strcpy(tmpbuf, &(t[5])); |
| if ((p = strchr(tmpbuf, '@')) == 0) { |
| (void) strcpy(parse_err_msg, "bad cname"); |
| return (GENENT_PARSEERR); |
| } |
| *(p++) = 0; |
| if (isdigit(*tmpbuf)) { |
| |
| uid = atoi(tmpbuf); |
| /* |
| * don't generate entries for uids without passwd entries |
| */ |
| if ((pwd = getpwuid(uid)) == 0) { |
| (void) fprintf(stderr, |
| gettext("can't map uid %d to username, skipping\n"), |
| uid); |
| return (GENENT_OK); |
| } |
| (void) strcpy(cname, pwd->pw_name); |
| data.hostcred = NS_HOSTCRED_FALSE; |
| } else { |
| if ((hp = gethostbyname(tmpbuf)) == 0) { |
| (void) fprintf(stderr, |
| gettext("can't map hostname %s to hostaddress, skipping\n"), |
| tmpbuf); |
| return (GENENT_OK); |
| } |
| (void) memcpy((char *)&in.s_addr, hp->h_addr_list[0], |
| sizeof (in)); |
| data.hostcred = NS_HOSTCRED_TRUE; |
| (void) snprintf(cname, sizeof (cname), |
| "%s+ipHostNumber=%s", tmpbuf, inet_ntoa(in)); |
| } |
| |
| ecol[0].ec_value.ec_value_val = cname; |
| ecol[0].ec_value.ec_value_len = strlen(cname)+1; |
| |
| /* |
| * public_data (col 1) |
| */ |
| if ((t = strtok(NULL, " \t")) == 0) { |
| (void) strcpy(parse_err_msg, "no private_data"); |
| return (GENENT_PARSEERR); |
| } |
| if ((p = strchr(t, ':')) == 0) { |
| (void) strcpy(parse_err_msg, "bad public_data"); |
| return (GENENT_PARSEERR); |
| } |
| *(p++) = 0; |
| ecol[1].ec_value.ec_value_val = t; |
| ecol[1].ec_value.ec_value_len = strlen(t)+1; |
| keylen = (strlen(t) / 2) * 8; |
| |
| /* |
| * private_data (col 2) and algtype extraction |
| */ |
| if (*p == ':') |
| p++; |
| t = p; |
| if (!(t = strchr(t, ':'))) { |
| (void) fprintf(stderr, |
| gettext("WARNING: No algorithm type data found " |
| "in publickey file, assuming 0\n")); |
| algtype = 0; |
| } else { |
| *t = '\0'; |
| t++; |
| algtype = atoi(t); |
| } |
| ecol[2].ec_value.ec_value_val = p; |
| ecol[2].ec_value.ec_value_len = strlen(p)+1; |
| |
| /* |
| * auth_type (col 1) |
| */ |
| if (!(__nis_keyalg2authtype(keylen, algtype, auth_type, |
| MECH_MAXATNAME))) { |
| (void) fprintf(stderr, |
| gettext("Could not convert algorithm type to " |
| "corresponding auth type string\n")); |
| return (GENENT_ERR); |
| } |
| |
| /* |
| * build entry |
| */ |
| data.name = strdup(ecol[0].ec_value.ec_value_val); |
| if (data.name == NULL) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| |
| buflen = sizeof (auth_type) + strlen(ecol[1].ec_value.ec_value_val) + 3; |
| if ((tmppubkey = (char *)malloc(buflen)) == NULL) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| (void) snprintf(tmppubkey, buflen, "{%s}%s", auth_type, |
| ecol[1].ec_value.ec_value_val); |
| data.pubkey = tmppubkey; |
| |
| buflen = sizeof (auth_type) + strlen(ecol[2].ec_value.ec_value_val) + 3; |
| if ((tmpprivkey = (char *)malloc(buflen)) == NULL) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| |
| (void) snprintf(tmpprivkey, buflen, "{%s}%s", auth_type, |
| ecol[2].ec_value.ec_value_val); |
| data.privkey = tmpprivkey; |
| |
| retval = (*cback)(&data, 1); |
| |
| if ((retval != NS_LDAP_SUCCESS) && (continue_onerror == 0)) |
| return (GENENT_CBERR); |
| else { |
| free(data.name); |
| free(data.pubkey); |
| free(data.privkey); |
| return (GENENT_OK); |
| } |
| } |
| |
| static void |
| dump_publickey(ns_ldap_result_t *res, char *container) |
| { |
| char **value = NULL; |
| char buf[BUFSIZ]; |
| char domainname[BUFSIZ]; |
| char *pubptr, *prvptr; |
| |
| if (res == NULL) |
| return; |
| |
| if (sysinfo(SI_SRPC_DOMAIN, domainname, BUFSIZ) < 0) { |
| (void) fprintf(stderr, |
| gettext("could not obtain domainname\n")); |
| exit(1); |
| } |
| |
| /* |
| * Retrieve all the attributes, but don't print |
| * until we have all the required ones. |
| */ |
| |
| if (strcmp(container, "passwd") == 0) |
| value = __ns_ldap_getAttr(res->entry, "uidNumber"); |
| else |
| value = __ns_ldap_getAttr(res->entry, "cn"); |
| |
| if (value && value[0]) |
| (void) snprintf(buf, sizeof (buf), "unix.%s@%s", |
| value[0], domainname); |
| else |
| return; |
| |
| value = __ns_ldap_getAttr(res->entry, "nisPublickey"); |
| if (value != NULL && value[0] != NULL) { |
| if ((pubptr = strchr(value[0], '}')) == NULL) |
| return; |
| } |
| |
| value = __ns_ldap_getAttr(res->entry, "nisSecretkey"); |
| if (value != NULL && value[0] != NULL) |
| if ((prvptr = strchr(value[0], '}')) == NULL) |
| return; |
| |
| /* print the attributes, algorithm type is always 0 */ |
| (void) fprintf(stdout, "%s %s:%s:0\n", buf, ++pubptr, ++prvptr); |
| } |
| |
| |
| |
| /* |
| * /etc/netmasks |
| */ |
| |
| static int |
| genent_netmasks(char *line, int (*cback)()) |
| { |
| char buf[BUFSIZ+1]; |
| char *t; |
| entry_col ecol[3]; |
| |
| struct _ns_netmasks data; |
| |
| |
| /* |
| * don't clobber our argument |
| */ |
| if (strlen(line) >= sizeof (buf)) { |
| (void) strcpy(parse_err_msg, "line too long"); |
| return (GENENT_PARSEERR); |
| } |
| (void) strcpy(buf, line); |
| |
| /* |
| * clear column data |
| */ |
| (void) memset((char *)ecol, 0, sizeof (ecol)); |
| |
| /* |
| * comment (col 2) |
| */ |
| t = strchr(buf, '#'); |
| if (t) { |
| *t++ = 0; |
| ecol[2].ec_value.ec_value_val = t; |
| ecol[2].ec_value.ec_value_len = strlen(t)+1; |
| } else { |
| ecol[2].ec_value.ec_value_val = 0; |
| ecol[2].ec_value.ec_value_len = 0; |
| } |
| |
| /* |
| * addr(col 0) |
| */ |
| if ((t = strtok(buf, " \t")) == 0) { |
| (void) strcpy(parse_err_msg, "no mask"); |
| return (GENENT_PARSEERR); |
| } |
| ecol[0].ec_value.ec_value_val = t; |
| ecol[0].ec_value.ec_value_len = strlen(t)+1; |
| |
| /* |
| * mask (col 1) |
| */ |
| if ((t = strtok(NULL, " \t")) == 0) { |
| (void) strcpy(parse_err_msg, "no mask"); |
| return (GENENT_PARSEERR); |
| } |
| ecol[1].ec_value.ec_value_val = t; |
| ecol[1].ec_value.ec_value_len = strlen(t)+1; |
| |
| /* build entry */ |
| data.netnumber = ecol[0].ec_value.ec_value_val; |
| data.netmask = ecol[1].ec_value.ec_value_val; |
| |
| if (flags & F_VERBOSE) |
| (void) fprintf(stdout, |
| gettext("Adding entry : %s\n"), data.netnumber); |
| |
| if ((*cback)(&data, 1) && continue_onerror == 0) |
| return (GENENT_CBERR); |
| |
| return (GENENT_OK); |
| } |
| |
| static void |
| dump_netmasks(ns_ldap_result_t *res) |
| { |
| char **value = NULL; |
| |
| value = __ns_ldap_getAttr(res->entry, "ipNetworkNumber"); |
| if (value && value[0]) |
| (void) fprintf(stdout, "%s", value[0]); |
| value = __ns_ldap_getAttr(res->entry, "ipNetmaskNumber"); |
| if (value && value[0]) |
| (void) fprintf(stdout, " %s\n", value[0]); |
| } |
| |
| |
| /* |
| * /etc/netgroup |
| * column data format is: |
| * col 0: netgroup name (or cname) |
| * col 1: netgroup member, if this is a triplet |
| * col 2: netgroup member, if not a triplet |
| * col 3: comment |
| */ |
| |
| static int |
| genent_netgroup(char *line, int (*cback)()) |
| { |
| char buf[BIGBUF+1]; /* netgroup entries tend to be big */ |
| char *t; |
| char *cname = NULL; |
| entry_col ecol[4]; |
| char *netg_tmp = NULL, *triplet_tmp = NULL; |
| int netgcount = 0, tripletcount = 0, retval = 1, i; |
| struct _ns_netgroups data; |
| int rc = GENENT_OK; |
| |
| /* don't clobber our argument */ |
| if (strlen(line) >= sizeof (buf)) { |
| (void) strcpy(parse_err_msg, "line too long"); |
| return (GENENT_PARSEERR); |
| } |
| (void) strcpy(buf, line); |
| |
| /* clear column data */ |
| (void) memset((char *)ecol, 0, sizeof (ecol)); |
| |
| /* |
| * process 1st minimal entry, to validate that there is no |
| * parsing error. |
| * start with comment(col 3) |
| */ |
| t = strchr(buf, '#'); |
| if (t) { |
| *t++ = 0; |
| ecol[3].ec_value.ec_value_val = t; |
| ecol[3].ec_value.ec_value_len = strlen(t)+1; |
| } else { |
| ecol[3].ec_value.ec_value_val = ""; |
| ecol[3].ec_value.ec_value_len = 0; |
| } |
| |
| ecol[1].ec_value.ec_value_val = NULL; |
| ecol[2].ec_value.ec_value_val = NULL; |
| |
| /* cname (col 0) */ |
| if ((t = strtok(buf, " \t")) == 0) { |
| (void) strcpy(parse_err_msg, "no cname"); |
| return (GENENT_PARSEERR); |
| } |
| |
| ecol[0].ec_value.ec_value_val = t; |
| ecol[0].ec_value.ec_value_len = strlen(t)+1; |
| cname = t; |
| |
| /* addr(col 1 and 2) */ |
| if ((t = strtok(NULL, " \t")) == 0) { |
| (void) strcpy(parse_err_msg, "no members for netgroup"); |
| return (GENENT_PARSEERR); |
| } |
| |
| if (*t == '(') { |
| /* if token starts with '(' it must be a valid triplet */ |
| if (is_triplet(t)) { |
| ecol[1].ec_value.ec_value_val = t; |
| ecol[1].ec_value.ec_value_len = strlen(t)+1; |
| } else { |
| (void) strcpy(parse_err_msg, "invalid triplet"); |
| return (GENENT_PARSEERR); |
| } |
| } else { |
| ecol[2].ec_value.ec_value_val = t; |
| ecol[2].ec_value.ec_value_len = strlen(t)+1; |
| } |
| |
| /* |
| * now build entry. |
| * start by clearing entry data |
| */ |
| (void) memset((struct _ns_netgroups *)&data, 0, sizeof (data)); |
| |
| data.name = strdup(ecol[0].ec_value.ec_value_val); |
| |
| if (ecol[1].ec_value.ec_value_val != NULL) { |
| if ((data.triplet = calloc(1, sizeof (char **))) == NULL) { |
| (void) fprintf(stderr, |
| gettext("out of memory\n")); |
| exit(1); |
| } |
| data.triplet[tripletcount++] = |
| strdup(ecol[1].ec_value.ec_value_val); |
| } else if (ecol[2].ec_value.ec_value_val != NULL) { |
| if ((data.netgroup = calloc(1, sizeof (char **))) |
| == NULL) { |
| (void) fprintf(stderr, |
| gettext("out of memory\n")); |
| exit(1); |
| } |
| data.netgroup[netgcount++] = |
| strdup(ecol[2].ec_value.ec_value_val); |
| } |
| |
| /* |
| * we now have a valid entry (at least 1 netgroup name and |
| * 1 netgroup member), proceed with the rest of the line |
| */ |
| while (rc == GENENT_OK && (t = strtok(NULL, " \t"))) { |
| |
| /* if next token is equal to netgroup name, ignore */ |
| if (t != cname && strcasecmp(t, cname) == 0) |
| continue; |
| if (strcasecmp(t, ecol[0].ec_value.ec_value_val) == 0) |
| continue; |
| |
| if (*t == '(') { |
| if (is_triplet(t)) { |
| /* skip a triplet if it is added already */ |
| for (i = 0; i < tripletcount && |
| strcmp(t, data.triplet[i]); i++) |
| ; |
| if (i < tripletcount) |
| continue; |
| |
| tripletcount++; |
| triplet_tmp = strdup(t); |
| if ((data.triplet = (char **)realloc( |
| data.triplet, |
| tripletcount * sizeof (char **))) |
| == NULL) { |
| (void) fprintf(stderr, |
| gettext("out of memory\n")); |
| exit(1); |
| } |
| data.triplet[tripletcount-1] = triplet_tmp; |
| } else { |
| (void) strcpy(parse_err_msg, "invalid triplet"); |
| rc = GENENT_PARSEERR; |
| } |
| } else { |
| /* skip a netgroup if it is added already */ |
| for (i = 0; i < netgcount && |
| strcmp(t, data.netgroup[i]); i++) |
| ; |
| if (i < netgcount) |
| continue; |
| |
| netgcount++; |
| netg_tmp = strdup(t); |
| if ((data.netgroup = (char **)realloc(data.netgroup, |
| netgcount * sizeof (char **))) == NULL) { |
| (void) fprintf(stderr, |
| gettext("out of memory\n")); |
| exit(1); |
| } |
| data.netgroup[netgcount-1] = netg_tmp; |
| } |
| } |
| |
| /* End the list with NULL */ |
| if ((data.triplet = (char **)realloc(data.triplet, |
| (tripletcount + 1) * sizeof (char **))) == NULL) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| data.triplet[tripletcount] = NULL; |
| if ((data.netgroup = (char **)realloc(data.netgroup, |
| (netgcount + 1) * sizeof (char **))) == NULL) { |
| (void) fprintf(stderr, gettext("out of memory\n")); |
| exit(1); |
| } |
| data.netgroup[netgcount] = NULL; |
| |
| if (rc == GENENT_OK) { |
| if (flags & F_VERBOSE) |
| (void) fprintf(stdout, |
| gettext("Adding entry : %s\n"), data.name); |
| |
| retval = (*cback)(&data, 0); |
| |
| if (retval == LDAP_ALREADY_EXISTS) { |
| if (continue_onerror) |
| (void) fprintf(stderr, gettext( |
| "Entry: %s - already Exists, skipping it.\n"), |
| data.name); |
| else { |
| rc = GENENT_CBERR; |
| (void) fprintf(stderr, |
| gettext("Entry: %s - already Exists\n"), |
| data.name); |
| } |
| } else if (retval) |
| rc = GENENT_CBERR; |
| } |
| |
| /* release memory allocated by strdup() */ |
| for (i = 0; i < tripletcount; i++) { |
| free(data.triplet[i]); |
| } |
| for (i = 0; i < netgcount; i++) { |
| free(data.netgroup[i]); |
| } |
| |
| free(data.name); |
| free(data.triplet); |
| free(data.netgroup); |
| |
| return (rc); |
| } |
| |
| static void |
| dump_netgroup(ns_ldap_result_t *res) |
| { |
| char **value = NULL; |
| int attr_count = 0; |
| |
| value = __ns_ldap_getAttr(res->entry, "cn"); |
| if ((value != NULL) && (value[0] != NULL)) |
| (void) fprintf(stdout, "%s", value[0]); |
| else |
| return; |
| value = __ns_ldap_getAttr(res->entry, "nisNetgroupTriple"); |
| if (value != NULL) |
| while (value[attr_count] != NULL) { |
| (void) fprintf(stdout, <
|