10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*2830Sdjl * Common Development and Distribution License (the "License").
6*2830Sdjl * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*2830Sdjl * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
270Sstevel@tonic-gate
280Sstevel@tonic-gate #include <ctype.h>
290Sstevel@tonic-gate #include <netdb.h>
300Sstevel@tonic-gate #include "ns_internal.h"
310Sstevel@tonic-gate #include "ldap_common.h"
320Sstevel@tonic-gate
330Sstevel@tonic-gate /* protocols attributes filters */
340Sstevel@tonic-gate #define _P_NAME "cn"
350Sstevel@tonic-gate #define _P_PROTO "ipprotocolnumber"
360Sstevel@tonic-gate #define _F_GETPROTOBYNAME "(&(objectClass=ipProtocol)(cn=%s))"
370Sstevel@tonic-gate #define _F_GETPROTOBYNAME_SSD "(&(%%s)(cn=%s))"
380Sstevel@tonic-gate #define _F_GETPROTOBYNUMBER \
390Sstevel@tonic-gate "(&(objectClass=ipProtocol)(ipProtocolNumber=%d))"
400Sstevel@tonic-gate #define _F_GETPROTOBYNUMBER_SSD \
410Sstevel@tonic-gate "(&(%%s)(ipProtocolNumber=%d))"
420Sstevel@tonic-gate
430Sstevel@tonic-gate static const char *protocols_attrs[] = {
440Sstevel@tonic-gate _P_NAME,
450Sstevel@tonic-gate _P_PROTO,
460Sstevel@tonic-gate (char *)NULL
470Sstevel@tonic-gate };
480Sstevel@tonic-gate
49*2830Sdjl typedef struct protocol_alias {
50*2830Sdjl char *protocol;
51*2830Sdjl char *alias;
52*2830Sdjl } protocol_alias_t;
53*2830Sdjl
54*2830Sdjl static const protocol_alias_t ip_aliases[10] = {
55*2830Sdjl { "ip", "IP" },
56*2830Sdjl { "ipip", "IP-IP" },
57*2830Sdjl { "ipcomp", "IPComp" },
58*2830Sdjl { "ipv6", "IPv6" },
59*2830Sdjl { "ipv6-route", "IPv6-Route" },
60*2830Sdjl { "ipv6-frag", "IPv6-Frag" },
61*2830Sdjl { "ipv6-icmp", "IPv6-ICMP" },
62*2830Sdjl { "ipv6-nonxt", "IPv6-NoNxt" },
63*2830Sdjl { "ipv6-opts", "IPv6-Opts" },
64*2830Sdjl { NULL, NULL }
65*2830Sdjl };
660Sstevel@tonic-gate
670Sstevel@tonic-gate /*
68*2830Sdjl * When the data is imported by ldapaddent, it does not save the aliase in the
69*2830Sdjl * "cn" that is same as the canonical name but only different in case.
70*2830Sdjl * e.g.
71*2830Sdjl * icmp 1 ICMP
72*2830Sdjl *
73*2830Sdjl * is saved as
74*2830Sdjl *
75*2830Sdjl * dn: cn=icmp, ...
76*2830Sdjl * ...
77*2830Sdjl * cn: icmp
78*2830Sdjl * ...
79*2830Sdjl *
80*2830Sdjl * So it needs to replicate the canonical name as an alias of upper case.
81*2830Sdjl * But some protocol does have different aliases.
82*2830Sdjl *
83*2830Sdjl * e.g.
84*2830Sdjl * dn: cn=ospf, ...
85*2830Sdjl * ...
86*2830Sdjl * cn: ospf
87*2830Sdjl * cn: OSPFIGP
88*2830Sdjl * ...
89*2830Sdjl *
90*2830Sdjl * For many ip* protocols, the aliases are mixed cased. Maybe it's case
91*2830Sdjl * insensitive. But this fucntion tries to restore the aliases to the original
92*2830Sdjl * form as much as possible. If the alias can't be found in the aliases table,
93*2830Sdjl * it assumes the alias is all upper case.
94*2830Sdjl *
95*2830Sdjl */
96*2830Sdjl static char *
get_alias(char * protocol)97*2830Sdjl get_alias(char *protocol) {
98*2830Sdjl int i;
99*2830Sdjl char *cp;
100*2830Sdjl
101*2830Sdjl if (strncmp(protocol, "ip", 2) == 0) {
102*2830Sdjl for (i = 0; ip_aliases[i].protocol != NULL; i++) {
103*2830Sdjl if (strcmp(protocol, ip_aliases[i].protocol) == 0)
104*2830Sdjl return (ip_aliases[i].alias);
105*2830Sdjl }
106*2830Sdjl /*
107*2830Sdjl * No aliase in the table. Return an all upper case aliase
108*2830Sdjl */
109*2830Sdjl for (cp = protocol; *cp; cp++)
110*2830Sdjl *cp = toupper(*cp);
111*2830Sdjl
112*2830Sdjl return (protocol);
113*2830Sdjl } else {
114*2830Sdjl /* Return an all upper case aliase */
115*2830Sdjl for (cp = protocol; *cp; cp++)
116*2830Sdjl *cp = toupper(*cp);
117*2830Sdjl
118*2830Sdjl return (protocol);
119*2830Sdjl }
120*2830Sdjl
121*2830Sdjl }
122*2830Sdjl /*
123*2830Sdjl * _nss_ldap_protocols2str is the data marshaling method for the protocols
1240Sstevel@tonic-gate * getXbyY * (e.g., getbyname(), getbynumber(), getent()) backend processes.
1250Sstevel@tonic-gate * This method is called after a successful ldap search has been performed.
126*2830Sdjl * This method will parse the ldap search values into a file format.
127*2830Sdjl * e.g.
128*2830Sdjl * idrp 45 IDRP
129*2830Sdjl * or
130*2830Sdjl * ospf 89 OSPFIGP
1310Sstevel@tonic-gate */
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate static int
_nss_ldap_protocols2str(ldap_backend_ptr be,nss_XbyY_args_t * argp)134*2830Sdjl _nss_ldap_protocols2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
1350Sstevel@tonic-gate {
136*2830Sdjl uint_t i;
1370Sstevel@tonic-gate int nss_result;
138*2830Sdjl int buflen = 0, len;
139*2830Sdjl char *cname = NULL;
140*2830Sdjl char *buffer = NULL, **number, *alias;
1410Sstevel@tonic-gate ns_ldap_result_t *result = be->result;
142*2830Sdjl ns_ldap_attr_t *names;
143*2830Sdjl
144*2830Sdjl if (result == NULL)
145*2830Sdjl return (NSS_STR_PARSE_PARSE);
1460Sstevel@tonic-gate
147*2830Sdjl buflen = argp->buf.buflen;
148*2830Sdjl if (argp->buf.result != NULL) {
149*2830Sdjl if ((be->buffer = calloc(1, buflen)) == NULL) {
150*2830Sdjl nss_result = NSS_STR_PARSE_PARSE;
151*2830Sdjl goto result_pls2str;
152*2830Sdjl }
153*2830Sdjl buffer = be->buffer;
154*2830Sdjl } else
155*2830Sdjl buffer = argp->buf.buffer;
1560Sstevel@tonic-gate
157*2830Sdjl nss_result = NSS_STR_PARSE_SUCCESS;
1580Sstevel@tonic-gate (void) memset(argp->buf.buffer, 0, buflen);
1590Sstevel@tonic-gate
160*2830Sdjl names = __ns_ldap_getAttrStruct(result->entry, _P_NAME);
161*2830Sdjl if (names == NULL || names->attrvalue == NULL) {
162*2830Sdjl nss_result = NSS_STR_PARSE_PARSE;
163*2830Sdjl goto result_pls2str;
164*2830Sdjl }
165*2830Sdjl /* Get the canonical name */
166*2830Sdjl cname = __s_api_get_canonical_name(result->entry, names, 1);
167*2830Sdjl if (cname == NULL || (len = strlen(cname)) < 1) {
168*2830Sdjl nss_result = NSS_STR_PARSE_PARSE;
169*2830Sdjl goto result_pls2str;
170*2830Sdjl }
171*2830Sdjl number = __ns_ldap_getAttr(result->entry, _P_PROTO);
172*2830Sdjl if (number == NULL || number[0] == NULL ||
173*2830Sdjl (len = strlen(number[0])) < 1) {
174*2830Sdjl nss_result = NSS_STR_PARSE_PARSE;
175*2830Sdjl goto result_pls2str;
1760Sstevel@tonic-gate }
177*2830Sdjl len = snprintf(buffer, buflen, "%s %s", cname, number[0]);
178*2830Sdjl TEST_AND_ADJUST(len, buffer, buflen, result_pls2str);
179*2830Sdjl /* Append aliases */
180*2830Sdjl if (names->value_count == 1) {
181*2830Sdjl /* create an aliase from protocol name */
182*2830Sdjl alias = get_alias(cname);
183*2830Sdjl len = snprintf(buffer, buflen, " %s", alias);
184*2830Sdjl TEST_AND_ADJUST(len, buffer, buflen, result_pls2str);
185*2830Sdjl
186*2830Sdjl } else {
187*2830Sdjl for (i = 0; i < names->value_count; i++) {
188*2830Sdjl if (names->attrvalue[i] == NULL) {
189*2830Sdjl nss_result = NSS_STR_PARSE_PARSE;
190*2830Sdjl goto result_pls2str;
1910Sstevel@tonic-gate }
192*2830Sdjl /* Skip the canonical name */
193*2830Sdjl if (strcasecmp(names->attrvalue[i], cname) != 0) {
194*2830Sdjl len = snprintf(buffer, buflen, " %s",
195*2830Sdjl names->attrvalue[i]);
196*2830Sdjl TEST_AND_ADJUST(len, buffer, buflen,
197*2830Sdjl result_pls2str);
1980Sstevel@tonic-gate }
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate }
2010Sstevel@tonic-gate
202*2830Sdjl /* The front end marshaller doesn't need to copy trailing nulls */
203*2830Sdjl if (argp->buf.result != NULL)
204*2830Sdjl be->buflen = strlen(be->buffer);
2050Sstevel@tonic-gate
206*2830Sdjl result_pls2str:
2070Sstevel@tonic-gate
2080Sstevel@tonic-gate (void) __ns_ldap_freeResult(&be->result);
2090Sstevel@tonic-gate return ((int)nss_result);
2100Sstevel@tonic-gate }
2110Sstevel@tonic-gate
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate /*
2140Sstevel@tonic-gate * getbyname gets struct protoent values by protocol name. This
2150Sstevel@tonic-gate * function constructs an ldap search filter using the protocol
2160Sstevel@tonic-gate * name invocation parameter and the getprotobyname search filter
2170Sstevel@tonic-gate * defined. Once the filter is constructed, we search for a matching
2180Sstevel@tonic-gate * entry and marshal the data results into *proto = (struct *
2190Sstevel@tonic-gate * protoent *)argp->buf.result. The function _nss_ldap_protocols2ent
2200Sstevel@tonic-gate * performs the data marshaling.
2210Sstevel@tonic-gate */
2220Sstevel@tonic-gate
2230Sstevel@tonic-gate static nss_status_t
getbyname(ldap_backend_ptr be,void * a)2240Sstevel@tonic-gate getbyname(ldap_backend_ptr be, void *a)
2250Sstevel@tonic-gate {
2260Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
2270Sstevel@tonic-gate char searchfilter[SEARCHFILTERLEN];
2280Sstevel@tonic-gate char userdata[SEARCHFILTERLEN];
2290Sstevel@tonic-gate char name[SEARCHFILTERLEN];
2300Sstevel@tonic-gate int ret;
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
2330Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
2340Sstevel@tonic-gate
2350Sstevel@tonic-gate ret = snprintf(searchfilter, sizeof (searchfilter),
2360Sstevel@tonic-gate _F_GETPROTOBYNAME, name);
2370Sstevel@tonic-gate if (ret >= sizeof (searchfilter) || ret < 0)
2380Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
2390Sstevel@tonic-gate
2400Sstevel@tonic-gate ret = snprintf(userdata, sizeof (userdata),
2410Sstevel@tonic-gate _F_GETPROTOBYNAME_SSD, name);
2420Sstevel@tonic-gate if (ret >= sizeof (userdata) || ret < 0)
2430Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate return ((nss_status_t)_nss_ldap_lookup(be, argp,
2460Sstevel@tonic-gate _PROTOCOLS, searchfilter, NULL,
2470Sstevel@tonic-gate _merge_SSD_filter, userdata));
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate /*
2520Sstevel@tonic-gate * getbynumber gets struct protoent values by protocol number. This
2530Sstevel@tonic-gate * function constructs an ldap search filter using the protocol
2540Sstevel@tonic-gate * name invocation parameter and the getprotobynumber search filter
2550Sstevel@tonic-gate * defined. Once the filter is constructed, we search for a matching
2560Sstevel@tonic-gate * entry and marshal the data results into *proto = (struct *
2570Sstevel@tonic-gate * protoent *)argp->buf.result. The function _nss_ldap_protocols2ent
2580Sstevel@tonic-gate * performs the data marshaling.
2590Sstevel@tonic-gate */
2600Sstevel@tonic-gate
2610Sstevel@tonic-gate static nss_status_t
getbynumber(ldap_backend_ptr be,void * a)2620Sstevel@tonic-gate getbynumber(ldap_backend_ptr be, void *a)
2630Sstevel@tonic-gate {
2640Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
2650Sstevel@tonic-gate char searchfilter[SEARCHFILTERLEN];
2660Sstevel@tonic-gate char userdata[SEARCHFILTERLEN];
2670Sstevel@tonic-gate int ret;
2680Sstevel@tonic-gate
2690Sstevel@tonic-gate ret = snprintf(searchfilter, sizeof (searchfilter),
2700Sstevel@tonic-gate _F_GETPROTOBYNUMBER, argp->key.number);
2710Sstevel@tonic-gate if (ret >= sizeof (searchfilter) || ret < 0)
2720Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate ret = snprintf(userdata, sizeof (userdata),
2750Sstevel@tonic-gate _F_GETPROTOBYNUMBER_SSD, argp->key.number);
2760Sstevel@tonic-gate if (ret >= sizeof (userdata) || ret < 0)
2770Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
2780Sstevel@tonic-gate
2790Sstevel@tonic-gate return ((nss_status_t)_nss_ldap_lookup(be, argp,
2800Sstevel@tonic-gate _PROTOCOLS, searchfilter, NULL,
2810Sstevel@tonic-gate _merge_SSD_filter, userdata));
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate static ldap_backend_op_t proto_ops[] = {
2850Sstevel@tonic-gate _nss_ldap_destr,
2860Sstevel@tonic-gate _nss_ldap_endent,
2870Sstevel@tonic-gate _nss_ldap_setent,
2880Sstevel@tonic-gate _nss_ldap_getent,
2890Sstevel@tonic-gate getbyname,
2900Sstevel@tonic-gate getbynumber
2910Sstevel@tonic-gate };
2920Sstevel@tonic-gate
2930Sstevel@tonic-gate
2940Sstevel@tonic-gate /*
2950Sstevel@tonic-gate * _nss_ldap_protocols_constr is where life begins. This function calls
2960Sstevel@tonic-gate * the generic ldap constructor function to define and build the abstract
2970Sstevel@tonic-gate * data types required to support ldap operations.
2980Sstevel@tonic-gate */
2990Sstevel@tonic-gate
3000Sstevel@tonic-gate /*ARGSUSED0*/
3010Sstevel@tonic-gate nss_backend_t *
_nss_ldap_protocols_constr(const char * dummy1,const char * dummy2,const char * dummy3)3020Sstevel@tonic-gate _nss_ldap_protocols_constr(const char *dummy1, const char *dummy2,
3030Sstevel@tonic-gate const char *dummy3)
3040Sstevel@tonic-gate {
3050Sstevel@tonic-gate
3060Sstevel@tonic-gate return ((nss_backend_t *)_nss_ldap_constr(proto_ops,
3070Sstevel@tonic-gate sizeof (proto_ops)/sizeof (proto_ops[0]), _PROTOCOLS,
308*2830Sdjl protocols_attrs, _nss_ldap_protocols2str));
3090Sstevel@tonic-gate }
310