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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <libintl.h> 32 #include <strings.h> 33 #include <locale.h> 34 #include <syslog.h> 35 #include "../../../lib/libsldap/common/ns_sldap.h" 36 37 extern char *set_filter(char **, char *, char **); 38 extern char *set_filter_publickey(char **, char *, int, char **); 39 extern void _printResult(ns_ldap_result_t *); 40 41 int listflag = 0; 42 43 void 44 usage(char *msg) { 45 if (msg) 46 fprintf(stderr, "%s\n", msg); 47 48 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 sprintf(buf, "%s (%s)", p, errorp->message); 136 __ns_ldap_freeError(&errorp); 137 } else 138 sprintf(buf, "%s", p); 139 *err = strdup(buf); 140 return (rc); 141 } 142 143 _printResult(result); 144 __ns_ldap_freeResult(&result); 145 return (0); 146 } 147 148 149 int 150 switch_err(int rc) 151 { 152 switch (rc) { 153 case NS_LDAP_SUCCESS: 154 return (0); 155 case NS_LDAP_NOTFOUND: 156 return (1); 157 } 158 return (2); 159 } 160 161 int 162 main(int argc, char **argv) 163 { 164 165 extern char *optarg; 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, repeat = 1; 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 case 'l': 195 attribute = "NULL"; 196 break; 197 case 'v': 198 verbose = 1; 199 break; 200 default: 201 usage(gettext("Invalid option")); 202 } 203 } 204 if ((c = argc - optind) > 0) 205 database = argv[optind++]; 206 if ((--c) > 0) 207 key = &argv[optind]; 208 209 /* 210 * If dumpping a database, 211 * or all the containers, 212 * use page control just 213 * in case there are too many entries 214 */ 215 if (!key && !(listflag & NS_LDAP_SCOPE_BASE)) 216 listflag |= NS_LDAP_PAGE_CTRL; 217 218 /* build the attribute array */ 219 if (strncasecmp(attribute, "NULL", 4) == 0) 220 ldapattribute = NULL; 221 else { 222 buffer[0] = strdup(attribute); 223 while ((p = strchr(attribute, ',')) != NULL) { 224 buffer[index++] = attribute = p + 1; 225 *p = '\0'; 226 } 227 buffer[index] = NULL; 228 ldapattribute = buffer; 229 } 230 231 /* build the filter */ 232 if (database && (strcasecmp(database, "publickey") == NULL)) { 233 /* user publickey lookup */ 234 char *err1 = NULL; 235 int rc1; 236 237 rc = rc1 = -1; 238 ldapfilter = set_filter_publickey(key, database, 0, &udata); 239 if (ldapfilter) { 240 if (verbose) { 241 fprintf(stdout, gettext("+++ database=%s\n"), 242 (database ? database : "NULL")); 243 fprintf(stdout, gettext("+++ filter=%s\n"), 244 (ldapfilter ? ldapfilter : "NULL")); 245 fprintf(stdout, 246 gettext("+++ template for merging" 247 "SSD filter=%s\n"), 248 (udata ? udata : "NULL")); 249 } 250 rc = list("passwd", ldapfilter, ldapattribute, 251 &err, udata); 252 free(ldapfilter); 253 free(udata); 254 } 255 /* hosts publickey lookup */ 256 ldapfilter = set_filter_publickey(key, database, 1, &udata); 257 if (ldapfilter) { 258 if (verbose) { 259 fprintf(stdout, gettext("+++ database=%s\n"), 260 (database ? database : "NULL")); 261 fprintf(stdout, gettext("+++ filter=%s\n"), 262 (ldapfilter ? ldapfilter : "NULL")); 263 fprintf(stdout, 264 gettext("+++ template for merging" 265 "SSD filter=%s\n"), 266 (udata ? udata : "NULL")); 267 } 268 rc1 = list("hosts", ldapfilter, ldapattribute, 269 &err1, udata); 270 free(ldapfilter); 271 free(udata); 272 } 273 if (rc == -1 && rc1 == -1) { 274 /* this should never happen */ 275 fprintf(stderr, 276 gettext("ldaplist: invalid publickey lookup\n")); 277 rc = 2; 278 } if (rc != 0 && rc1 != 0) { 279 fprintf(stderr, 280 gettext("ldaplist: %s\n"), (err ? err : err1)); 281 if (rc == -1) 282 rc = rc1; 283 } else 284 rc = 0; 285 exit(switch_err(rc)); 286 } 287 288 /* 289 * we set the search filter to (objectclass=*) when we want 290 * to list the directory attribute instead of the entries 291 * (the -d option). 292 */ 293 if (((ldapfilter = set_filter(key, database, &udata)) == NULL) || 294 (listflag == NS_LDAP_SCOPE_BASE)) { 295 ldapfilter = strdup("objectclass=*"); 296 udata = strdup("%s"); 297 } 298 299 if (verbose) { 300 fprintf(stdout, gettext("+++ database=%s\n"), 301 (database ? database : "NULL")); 302 fprintf(stdout, gettext("+++ filter=%s\n"), 303 (ldapfilter ? ldapfilter : "NULL")); 304 fprintf(stdout, 305 gettext("+++ template for merging SSD filter=%s\n"), 306 (udata ? udata : "NULL")); 307 } 308 if (rc = list(database, ldapfilter, ldapattribute, &err, udata)) 309 fprintf(stderr, gettext("ldaplist: %s\n"), err); 310 if (ldapfilter) 311 free(ldapfilter); 312 if (udata) 313 free(udata); 314 exit(switch_err(rc)); 315 } 316