1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <libintl.h> 31 #include <strings.h> 32 #include <locale.h> 33 #include <syslog.h> 34 #include "../../../lib/libsldap/common/ns_sldap.h" 35 36 extern char *set_filter(char **, char *, char **); 37 extern char *set_filter_publickey(char **, char *, int, char **); 38 extern void _printResult(ns_ldap_result_t *); 39 extern void printMapping(); 40 41 int listflag = 0; 42 43 void 44 usage(char *msg) { 45 if (msg) 46 (void) fprintf(stderr, "%s\n", msg); 47 48 (void) fprintf(stderr, 49 gettext( 50 "ldaplist [-lvh] [<database> [<key>] ...]\n" 51 "\tOptions:\n" 52 "\t -l list all the attributes found in entry.\n" 53 "\t By default, it lists only the DNs.\n" 54 "\t -d list attributes for the database instead of its entries\n" 55 "\t -v print out the LDAP search filter.\n" 56 "\t -h list the database mappings.\n" 57 "\t<database> is the database to be searched in. Standard system\n" 58 "\tdatabases are:\n" 59 "\t\tpassword, printers, group, hosts, ethers, networks, netmasks,\n" 60 "\t\trpc, bootparams, protocols, services, netgroup, auto_*.\n" 61 "\tNon-standard system databases can be specified as follows:\n" 62 "\t\tby specific container: ou=<dbname> or\n" 63 "\t\tby default container: <dbname>. In this case, 'nismapname'\n" 64 "\t\twill be used, thus mapping this to nismapname=<dbname>.\n" 65 "\t<key> is the key to search in the database. For the standard\n" 66 "\tdatabases, the search type for the key is predefined. You can\n" 67 "\toverride this by specifying <type>=<key>.\n")); 68 exit(1); 69 } 70 71 /* 72 * This is a generic filter call back function for 73 * merging the filter from service search descriptor with 74 * an existing search filter. This routine expects userdata 75 * contain a format string with a single %s in it, and will 76 * use the format string with sprintf() to insert the SSD filter. 77 * 78 * This routine is passed to the __ns_ldap_list() or 79 * __ns_ldap_firstEntry() APIs as the filter call back 80 * together with the userdata. For example, 81 * the "ldaplist hosts sys1" processing may call __ns_ldap_list() 82 * with "(&(objectClass=ipHost)(cn=sys1))" as filter, this function 83 * as the filter call back, and "(&(%s)(cn=sys1))" as the 84 * userdata, this routine will in turn gets call to produce 85 * "(&(department=sds)(cn=sys1))" as the real search 86 * filter, if the input SSD contains a filter "department=sds". 87 */ 88 static int 89 merge_SSD_filter(const ns_ldap_search_desc_t *desc, 90 char **realfilter, 91 const void *userdata) 92 { 93 int len; 94 95 /* sanity check */ 96 if (realfilter == NULL) 97 return (NS_LDAP_INVALID_PARAM); 98 *realfilter = NULL; 99 100 if (desc == NULL || desc->filter == NULL || 101 userdata == NULL) 102 return (NS_LDAP_INVALID_PARAM); 103 104 len = strlen(userdata) + strlen(desc->filter) + 1; 105 106 *realfilter = (char *)malloc(len); 107 if (*realfilter == NULL) 108 return (NS_LDAP_MEMORY); 109 110 (void) sprintf(*realfilter, (char *)userdata, 111 desc->filter); 112 113 return (NS_LDAP_SUCCESS); 114 } 115 116 /* returns 0=success, 1=error */ 117 int 118 list(char *database, char *ldapfilter, char **ldapattribute, 119 char **err, char *userdata) 120 { 121 ns_ldap_result_t *result; 122 ns_ldap_error_t *errorp; 123 int rc; 124 char buf[500]; 125 126 *err = NULL; 127 buf[0] = '\0'; 128 rc = __ns_ldap_list(database, (const char *)ldapfilter, 129 merge_SSD_filter, (const char **)ldapattribute, NULL, 130 listflag, &result, &errorp, NULL, userdata); 131 if (rc != NS_LDAP_SUCCESS) { 132 char *p; 133 (void) __ns_ldap_err2str(rc, &p); 134 if (errorp && errorp->message) { 135 (void) snprintf(buf, sizeof (buf), "%s (%s)", 136 p, errorp->message); 137 (void) __ns_ldap_freeError(&errorp); 138 } else 139 (void) snprintf(buf, sizeof (buf), "%s", p); 140 *err = strdup(buf); 141 return (rc); 142 } 143 144 _printResult(result); 145 (void) __ns_ldap_freeResult(&result); 146 return (0); 147 } 148 149 150 int 151 switch_err(int rc) 152 { 153 switch (rc) { 154 case NS_LDAP_SUCCESS: 155 return (0); 156 case NS_LDAP_NOTFOUND: 157 return (1); 158 } 159 return (2); 160 } 161 162 int 163 main(int argc, char **argv) 164 { 165 166 extern int optind; 167 char *database = NULL; 168 char *ldapfilter = NULL; 169 char *attribute = "dn"; 170 char **key = NULL; 171 char **ldapattribute = NULL; 172 char *buffer[100]; 173 char *err = NULL; 174 char *p; 175 int index = 1; 176 int c; 177 int rc; 178 int verbose = 0; 179 char *udata = NULL; 180 181 (void) setlocale(LC_ALL, ""); 182 (void) textdomain(TEXT_DOMAIN); 183 184 openlog("ldaplist", LOG_PID, LOG_USER); 185 186 while ((c = getopt(argc, argv, "dhvl")) != EOF) { 187 switch (c) { 188 case 'd': 189 listflag |= NS_LDAP_SCOPE_BASE; 190 break; 191 case 'h': 192 (void) printMapping(); 193 exit(0); 194 break; /* Never reached */ 195 case 'l': 196 attribute = "NULL"; 197 break; 198 case 'v': 199 verbose = 1; 200 break; 201 default: 202 usage(gettext("Invalid option")); 203 } 204 } 205 if ((c = argc - optind) > 0) 206 database = argv[optind++]; 207 if ((--c) > 0) 208 key = &argv[optind]; 209 210 /* 211 * If dumpping a database, 212 * or all the containers, 213 * use page control just 214 * in case there are too many entries 215 */ 216 if (!key && !(listflag & NS_LDAP_SCOPE_BASE)) 217 listflag |= NS_LDAP_PAGE_CTRL; 218 219 /* build the attribute array */ 220 if (strncasecmp(attribute, "NULL", 4) == 0) 221 ldapattribute = NULL; 222 else { 223 buffer[0] = strdup(attribute); 224 while ((p = strchr(attribute, ',')) != NULL) { 225 buffer[index++] = attribute = p + 1; 226 *p = '\0'; 227 } 228 buffer[index] = NULL; 229 ldapattribute = buffer; 230 } 231 232 /* build the filter */ 233 if (database && (strcasecmp(database, "publickey") == NULL)) { 234 /* user publickey lookup */ 235 char *err1 = NULL; 236 int rc1; 237 238 rc = rc1 = -1; 239 ldapfilter = set_filter_publickey(key, database, 0, &udata); 240 if (ldapfilter) { 241 if (verbose) { 242 (void) fprintf(stdout, 243 gettext("+++ database=%s\n"), 244 (database ? database : "NULL")); 245 (void) fprintf(stdout, 246 gettext("+++ filter=%s\n"), 247 (ldapfilter ? ldapfilter : "NULL")); 248 (void) fprintf(stdout, 249 gettext("+++ template for merging" 250 "SSD filter=%s\n"), 251 (udata ? udata : "NULL")); 252 } 253 rc = list("passwd", ldapfilter, ldapattribute, 254 &err, udata); 255 free(ldapfilter); 256 free(udata); 257 } 258 /* hosts publickey lookup */ 259 ldapfilter = set_filter_publickey(key, database, 1, &udata); 260 if (ldapfilter) { 261 if (verbose) { 262 (void) fprintf(stdout, 263 gettext("+++ database=%s\n"), 264 (database ? database : "NULL")); 265 (void) fprintf(stdout, 266 gettext("+++ filter=%s\n"), 267 (ldapfilter ? ldapfilter : "NULL")); 268 (void) fprintf(stdout, 269 gettext("+++ template for merging" 270 "SSD filter=%s\n"), 271 (udata ? udata : "NULL")); 272 } 273 rc1 = list("hosts", ldapfilter, ldapattribute, 274 &err1, udata); 275 free(ldapfilter); 276 free(udata); 277 } 278 if (rc == -1 && rc1 == -1) { 279 /* this should never happen */ 280 (void) fprintf(stderr, 281 gettext("ldaplist: invalid publickey lookup\n")); 282 rc = 2; 283 } if (rc != 0 && rc1 != 0) { 284 (void) fprintf(stderr, 285 gettext("ldaplist: %s\n"), (err ? err : err1)); 286 if (rc == -1) 287 rc = rc1; 288 } else 289 rc = 0; 290 exit(switch_err(rc)); 291 } 292 293 /* 294 * we set the search filter to (objectclass=*) when we want 295 * to list the directory attribute instead of the entries 296 * (the -d option). 297 */ 298 if (((ldapfilter = set_filter(key, database, &udata)) == NULL) || 299 (listflag == NS_LDAP_SCOPE_BASE)) { 300 ldapfilter = strdup("objectclass=*"); 301 udata = strdup("%s"); 302 } 303 304 if (verbose) { 305 (void) fprintf(stdout, gettext("+++ database=%s\n"), 306 (database ? database : "NULL")); 307 (void) fprintf(stdout, gettext("+++ filter=%s\n"), 308 (ldapfilter ? ldapfilter : "NULL")); 309 (void) fprintf(stdout, 310 gettext("+++ template for merging SSD filter=%s\n"), 311 (udata ? udata : "NULL")); 312 } 313 if (rc = list(database, ldapfilter, ldapattribute, &err, udata)) 314 (void) fprintf(stderr, gettext("ldaplist: %s\n"), err); 315 if (ldapfilter) 316 free(ldapfilter); 317 if (udata) 318 free(udata); 319 exit(switch_err(rc)); 320 return (0); /* Never reached */ 321 } 322