10Sstevel@tonic-gate /* 2*3857Sstevel * Portions Copyright 1998 Sun Microsystems, Inc. All rights reserved. 3*3857Sstevel * Use is subject to license terms. 40Sstevel@tonic-gate */ 50Sstevel@tonic-gate 60Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 70Sstevel@tonic-gate /* 80Sstevel@tonic-gate * Copyright (c) 1993, 1994 Regents of the University of Michigan. 90Sstevel@tonic-gate * All rights reserved. 100Sstevel@tonic-gate * 110Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted 120Sstevel@tonic-gate * provided that this notice is preserved and that due credit is given 130Sstevel@tonic-gate * to the University of Michigan at Ann Arbor. The name of the University 140Sstevel@tonic-gate * may not be used to endorse or promote products derived from this 150Sstevel@tonic-gate * software without specific prior written permission. This software 160Sstevel@tonic-gate * is provided ``as is'' without express or implied warranty. 170Sstevel@tonic-gate * 180Sstevel@tonic-gate * disptmpl.c: display template library routines for LDAP clients 190Sstevel@tonic-gate * 7 March 1994 by Mark C Smith 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate 220Sstevel@tonic-gate #include <stdio.h> 230Sstevel@tonic-gate #include <ctype.h> 240Sstevel@tonic-gate #include <string.h> 250Sstevel@tonic-gate #include <stdlib.h> 260Sstevel@tonic-gate #ifdef MACOS 270Sstevel@tonic-gate #include "macos.h" 280Sstevel@tonic-gate #else /* MACOS */ 290Sstevel@tonic-gate #ifdef DOS 300Sstevel@tonic-gate #include <malloc.h> 310Sstevel@tonic-gate #include "msdos.h" 320Sstevel@tonic-gate #else /* DOS */ 330Sstevel@tonic-gate #include <sys/types.h> 340Sstevel@tonic-gate #include <sys/file.h> 350Sstevel@tonic-gate #ifndef VMS 360Sstevel@tonic-gate #include <unistd.h> 370Sstevel@tonic-gate #endif /* VMS */ 380Sstevel@tonic-gate #endif /* DOS */ 390Sstevel@tonic-gate #endif /* MACOS */ 400Sstevel@tonic-gate 410Sstevel@tonic-gate #include "lber.h" 420Sstevel@tonic-gate #include "ldap.h" 430Sstevel@tonic-gate #include "ldap-private.h" 440Sstevel@tonic-gate #include "ldap-int.h" 450Sstevel@tonic-gate 460Sstevel@tonic-gate #ifndef NEEDPROTOS 470Sstevel@tonic-gate static void free_disptmpl(); 480Sstevel@tonic-gate static int read_next_tmpl(); 490Sstevel@tonic-gate int next_line_tokens(); 500Sstevel@tonic-gate #else /* !NEEDPROTOS */ 510Sstevel@tonic-gate static void free_disptmpl( struct ldap_disptmpl *tmpl ); 520Sstevel@tonic-gate static int read_next_tmpl( char **bufp, ssize_t *blenp, 530Sstevel@tonic-gate struct ldap_disptmpl **tmplp, int dtversion ); 540Sstevel@tonic-gate int next_line_tokens( char **bufp, ssize_t *blenp, char ***toksp ); 550Sstevel@tonic-gate #endif /* !NEEDPROTOS */ 560Sstevel@tonic-gate 570Sstevel@tonic-gate static char *tmploptions[] = { 580Sstevel@tonic-gate "addable", "modrdn", 590Sstevel@tonic-gate "altview", 600Sstevel@tonic-gate NULL 610Sstevel@tonic-gate }; 620Sstevel@tonic-gate 630Sstevel@tonic-gate 640Sstevel@tonic-gate static unsigned int tmploptvals[] = { 650Sstevel@tonic-gate LDAP_DTMPL_OPT_ADDABLE, LDAP_DTMPL_OPT_ALLOWMODRDN, 660Sstevel@tonic-gate LDAP_DTMPL_OPT_ALTVIEW, 670Sstevel@tonic-gate }; 680Sstevel@tonic-gate 690Sstevel@tonic-gate 700Sstevel@tonic-gate static char *itemtypes[] = { 710Sstevel@tonic-gate "cis", "mls", "dn", 720Sstevel@tonic-gate "bool", "jpeg", "jpegbtn", 730Sstevel@tonic-gate "fax", "faxbtn", "audiobtn", 740Sstevel@tonic-gate "time", "date", "url", 750Sstevel@tonic-gate "searchact", "linkact", "adddnact", 760Sstevel@tonic-gate "addact", "verifyact", "mail", 770Sstevel@tonic-gate #ifdef SUN 780Sstevel@tonic-gate "protected", 790Sstevel@tonic-gate #endif 800Sstevel@tonic-gate NULL 810Sstevel@tonic-gate }; 820Sstevel@tonic-gate 830Sstevel@tonic-gate static unsigned int itemsynids[] = { 840Sstevel@tonic-gate LDAP_SYN_CASEIGNORESTR, LDAP_SYN_MULTILINESTR, LDAP_SYN_DN, 850Sstevel@tonic-gate LDAP_SYN_BOOLEAN, LDAP_SYN_JPEGIMAGE, LDAP_SYN_JPEGBUTTON, 860Sstevel@tonic-gate LDAP_SYN_FAXIMAGE, LDAP_SYN_FAXBUTTON, LDAP_SYN_AUDIOBUTTON, 870Sstevel@tonic-gate LDAP_SYN_TIME, LDAP_SYN_DATE, LDAP_SYN_LABELEDURL, 880Sstevel@tonic-gate LDAP_SYN_SEARCHACTION, LDAP_SYN_LINKACTION, LDAP_SYN_ADDDNACTION, 890Sstevel@tonic-gate LDAP_SYN_ADDDNACTION, LDAP_SYN_VERIFYDNACTION,LDAP_SYN_RFC822ADDR, 900Sstevel@tonic-gate #ifdef SUN 910Sstevel@tonic-gate LDAP_SYN_PROTECTED, 920Sstevel@tonic-gate #endif 930Sstevel@tonic-gate }; 940Sstevel@tonic-gate 950Sstevel@tonic-gate 960Sstevel@tonic-gate static char *itemoptions[] = { 970Sstevel@tonic-gate "ro", "sort", 980Sstevel@tonic-gate "1val", "hide", 990Sstevel@tonic-gate "required", "hideiffalse", 1000Sstevel@tonic-gate NULL 1010Sstevel@tonic-gate }; 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate 1040Sstevel@tonic-gate static unsigned int itemoptvals[] = { 1050Sstevel@tonic-gate LDAP_DITEM_OPT_READONLY, LDAP_DITEM_OPT_SORTVALUES, 1060Sstevel@tonic-gate LDAP_DITEM_OPT_SINGLEVALUED, LDAP_DITEM_OPT_HIDEIFEMPTY, 1070Sstevel@tonic-gate LDAP_DITEM_OPT_VALUEREQUIRED, LDAP_DITEM_OPT_HIDEIFFALSE, 1080Sstevel@tonic-gate }; 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate #define ADDEF_CONSTANT "constant" 1120Sstevel@tonic-gate #define ADDEF_ADDERSDN "addersdn" 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate #ifdef SUN 1150Sstevel@tonic-gate /* LP@Sun : right_trim */ 1160Sstevel@tonic-gate static void right_trim(char *aStr) 1170Sstevel@tonic-gate { 1180Sstevel@tonic-gate char * theEnd = aStr + strlen(aStr); 1190Sstevel@tonic-gate while ((theEnd > aStr) && isspace(*(theEnd - 1))) 1200Sstevel@tonic-gate theEnd--; 1210Sstevel@tonic-gate theEnd; 1220Sstevel@tonic-gate *theEnd= '\0'; 1230Sstevel@tonic-gate } 1240Sstevel@tonic-gate #endif 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate int 1270Sstevel@tonic-gate ldap_init_templates( char *file, struct ldap_disptmpl **tmpllistp ) 1280Sstevel@tonic-gate { 1290Sstevel@tonic-gate FILE *fp; 1300Sstevel@tonic-gate char *buf; 1310Sstevel@tonic-gate ssize_t rlen, len; 1320Sstevel@tonic-gate int rc, eof; 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate *tmpllistp = NULLDISPTMPL; 1350Sstevel@tonic-gate 1360Sstevel@tonic-gate if (( fp = fopen( file, "r" )) == NULL ) { 1370Sstevel@tonic-gate return( LDAP_TMPL_ERR_FILE ); 1380Sstevel@tonic-gate } 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */ 1410Sstevel@tonic-gate fclose( fp ); 1420Sstevel@tonic-gate return( LDAP_TMPL_ERR_FILE ); 1430Sstevel@tonic-gate } 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate len = ftell( fp ); 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */ 1480Sstevel@tonic-gate fclose( fp ); 1490Sstevel@tonic-gate return( LDAP_TMPL_ERR_FILE ); 1500Sstevel@tonic-gate } 1510Sstevel@tonic-gate 1520Sstevel@tonic-gate if (( buf = malloc( len )) == NULL ) { 1530Sstevel@tonic-gate fclose( fp ); 1540Sstevel@tonic-gate return( LDAP_TMPL_ERR_MEM ); 1550Sstevel@tonic-gate } 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate rlen = fread( buf, (size_t) 1, len, fp ); 1580Sstevel@tonic-gate eof = feof( fp ); 1590Sstevel@tonic-gate fclose( fp ); 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate if ( rlen != len && !eof ) { /* error: didn't get the whole file */ 1620Sstevel@tonic-gate free( buf ); 1630Sstevel@tonic-gate return( LDAP_TMPL_ERR_FILE ); 1640Sstevel@tonic-gate } 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate rc = ldap_init_templates_buf( buf, rlen, tmpllistp ); 1670Sstevel@tonic-gate free( buf ); 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate return( rc ); 1700Sstevel@tonic-gate } 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate int 1740Sstevel@tonic-gate ldap_init_templates_buf( char *buf, ssize_t buflen, 1750Sstevel@tonic-gate struct ldap_disptmpl **tmpllistp ) 1760Sstevel@tonic-gate { 1770Sstevel@tonic-gate int rc, version; 1780Sstevel@tonic-gate char **toks; 1790Sstevel@tonic-gate struct ldap_disptmpl *prevtmpl, *tmpl; 1800Sstevel@tonic-gate 1810Sstevel@tonic-gate *tmpllistp = prevtmpl = NULLDISPTMPL; 1820Sstevel@tonic-gate 1830Sstevel@tonic-gate if ( next_line_tokens( &buf, &buflen, &toks ) != 2 || 1840Sstevel@tonic-gate strcasecmp( toks[ 0 ], "version" ) != 0 ) { 1850Sstevel@tonic-gate free_strarray( toks ); 1860Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 1870Sstevel@tonic-gate } 1880Sstevel@tonic-gate version = atoi( toks[ 1 ] ); 1890Sstevel@tonic-gate free_strarray( toks ); 1900Sstevel@tonic-gate if ( version != LDAP_TEMPLATE_VERSION ) { 1910Sstevel@tonic-gate return( LDAP_TMPL_ERR_VERSION ); 1920Sstevel@tonic-gate } 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate while ( buflen > 0 && ( rc = read_next_tmpl( &buf, &buflen, &tmpl, 1950Sstevel@tonic-gate version )) == 0 && tmpl != NULLDISPTMPL ) { 1960Sstevel@tonic-gate if ( prevtmpl == NULLDISPTMPL ) { 1970Sstevel@tonic-gate *tmpllistp = tmpl; 1980Sstevel@tonic-gate } else { 1990Sstevel@tonic-gate prevtmpl->dt_next = tmpl; 2000Sstevel@tonic-gate } 2010Sstevel@tonic-gate prevtmpl = tmpl; 2020Sstevel@tonic-gate } 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate if ( rc != 0 ) { 2050Sstevel@tonic-gate ldap_free_templates( *tmpllistp ); 2060Sstevel@tonic-gate } 2070Sstevel@tonic-gate 2080Sstevel@tonic-gate return( rc ); 2090Sstevel@tonic-gate } 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate void 2140Sstevel@tonic-gate ldap_free_templates( struct ldap_disptmpl *tmpllist ) 2150Sstevel@tonic-gate { 2160Sstevel@tonic-gate struct ldap_disptmpl *tp, *nexttp; 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate if ( tmpllist != NULL ) { 2190Sstevel@tonic-gate for ( tp = tmpllist; tp != NULL; tp = nexttp ) { 2200Sstevel@tonic-gate nexttp = tp->dt_next; 2210Sstevel@tonic-gate free_disptmpl( tp ); 2220Sstevel@tonic-gate } 2230Sstevel@tonic-gate } 2240Sstevel@tonic-gate } 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate 2270Sstevel@tonic-gate static void 2280Sstevel@tonic-gate free_disptmpl( struct ldap_disptmpl *tmpl ) 2290Sstevel@tonic-gate { 2300Sstevel@tonic-gate if ( tmpl != NULL ) { 2310Sstevel@tonic-gate if ( tmpl->dt_name != NULL ) { 2320Sstevel@tonic-gate free( tmpl->dt_name ); 2330Sstevel@tonic-gate } 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate if ( tmpl->dt_pluralname != NULL ) { 2360Sstevel@tonic-gate free( tmpl->dt_pluralname ); 2370Sstevel@tonic-gate } 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate if ( tmpl->dt_iconname != NULL ) { 2400Sstevel@tonic-gate free( tmpl->dt_iconname ); 2410Sstevel@tonic-gate } 2420Sstevel@tonic-gate 2430Sstevel@tonic-gate if ( tmpl->dt_authattrname != NULL ) { 2440Sstevel@tonic-gate free( tmpl->dt_authattrname ); 2450Sstevel@tonic-gate } 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate if ( tmpl->dt_defrdnattrname != NULL ) { 2480Sstevel@tonic-gate free( tmpl->dt_defrdnattrname ); 2490Sstevel@tonic-gate } 2500Sstevel@tonic-gate 2510Sstevel@tonic-gate if ( tmpl->dt_defaddlocation != NULL ) { 2520Sstevel@tonic-gate free( tmpl->dt_defaddlocation ); 2530Sstevel@tonic-gate } 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate if ( tmpl->dt_oclist != NULL ) { 2560Sstevel@tonic-gate struct ldap_oclist *ocp, *nextocp; 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate for ( ocp = tmpl->dt_oclist; ocp != NULL; ocp = nextocp ) { 2590Sstevel@tonic-gate nextocp = ocp->oc_next; 2600Sstevel@tonic-gate free_strarray( ocp->oc_objclasses ); 2610Sstevel@tonic-gate free( ocp ); 2620Sstevel@tonic-gate } 2630Sstevel@tonic-gate } 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate if ( tmpl->dt_adddeflist != NULL ) { 2660Sstevel@tonic-gate struct ldap_adddeflist *adp, *nextadp; 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate for ( adp = tmpl->dt_adddeflist; adp != NULL; adp = nextadp ) { 2690Sstevel@tonic-gate nextadp = adp->ad_next; 2700Sstevel@tonic-gate if( adp->ad_attrname != NULL ) { 2710Sstevel@tonic-gate free( adp->ad_attrname ); 2720Sstevel@tonic-gate } 2730Sstevel@tonic-gate if( adp->ad_value != NULL ) { 2740Sstevel@tonic-gate free( adp->ad_value ); 2750Sstevel@tonic-gate } 2760Sstevel@tonic-gate free( adp ); 2770Sstevel@tonic-gate } 2780Sstevel@tonic-gate } 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate if ( tmpl->dt_items != NULL ) { 2810Sstevel@tonic-gate struct ldap_tmplitem *rowp, *nextrowp, *colp, *nextcolp; 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate for ( rowp = tmpl->dt_items; rowp != NULL; rowp = nextrowp ) { 2840Sstevel@tonic-gate nextrowp = rowp->ti_next_in_col; 2850Sstevel@tonic-gate for ( colp = rowp; colp != NULL; colp = nextcolp ) { 2860Sstevel@tonic-gate nextcolp = colp->ti_next_in_row; 2870Sstevel@tonic-gate if ( colp->ti_attrname != NULL ) { 2880Sstevel@tonic-gate free( colp->ti_attrname ); 2890Sstevel@tonic-gate } 2900Sstevel@tonic-gate if ( colp->ti_label != NULL ) { 2910Sstevel@tonic-gate free( colp->ti_label ); 2920Sstevel@tonic-gate } 2930Sstevel@tonic-gate if ( colp->ti_args != NULL ) { 2940Sstevel@tonic-gate free_strarray( colp->ti_args ); 2950Sstevel@tonic-gate } 2960Sstevel@tonic-gate free( colp ); 2970Sstevel@tonic-gate } 2980Sstevel@tonic-gate } 2990Sstevel@tonic-gate } 3000Sstevel@tonic-gate 3010Sstevel@tonic-gate free( tmpl ); 3020Sstevel@tonic-gate } 3030Sstevel@tonic-gate } 3040Sstevel@tonic-gate 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate struct ldap_disptmpl * 3070Sstevel@tonic-gate ldap_first_disptmpl( struct ldap_disptmpl *tmpllist ) 3080Sstevel@tonic-gate { 3090Sstevel@tonic-gate return( tmpllist ); 3100Sstevel@tonic-gate } 3110Sstevel@tonic-gate 3120Sstevel@tonic-gate 3130Sstevel@tonic-gate struct ldap_disptmpl * 3140Sstevel@tonic-gate ldap_next_disptmpl( struct ldap_disptmpl *tmpllist, 3150Sstevel@tonic-gate struct ldap_disptmpl *tmpl ) 3160Sstevel@tonic-gate { 3170Sstevel@tonic-gate return( tmpl == NULLDISPTMPL ? tmpl : tmpl->dt_next ); 3180Sstevel@tonic-gate } 3190Sstevel@tonic-gate 3200Sstevel@tonic-gate 3210Sstevel@tonic-gate struct ldap_disptmpl * 3220Sstevel@tonic-gate ldap_name2template( char *name, struct ldap_disptmpl *tmpllist ) 3230Sstevel@tonic-gate { 3240Sstevel@tonic-gate struct ldap_disptmpl *dtp; 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL; 3270Sstevel@tonic-gate dtp = ldap_next_disptmpl( tmpllist, dtp )) { 3280Sstevel@tonic-gate if ( strcasecmp( name, dtp->dt_name ) == 0 ) { 3290Sstevel@tonic-gate return( dtp ); 3300Sstevel@tonic-gate } 3310Sstevel@tonic-gate } 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate return( NULLDISPTMPL ); 3340Sstevel@tonic-gate } 3350Sstevel@tonic-gate 3360Sstevel@tonic-gate 3370Sstevel@tonic-gate struct ldap_disptmpl * 3380Sstevel@tonic-gate ldap_oc2template( char **oclist, struct ldap_disptmpl *tmpllist ) 3390Sstevel@tonic-gate { 3400Sstevel@tonic-gate struct ldap_disptmpl *dtp; 3410Sstevel@tonic-gate struct ldap_oclist *oclp; 3420Sstevel@tonic-gate int i, j, needcnt, matchcnt; 3430Sstevel@tonic-gate 3440Sstevel@tonic-gate if ( tmpllist == NULL || oclist == NULL || oclist[ 0 ] == NULL ) { 3450Sstevel@tonic-gate return( NULLDISPTMPL ); 3460Sstevel@tonic-gate } 3470Sstevel@tonic-gate 3480Sstevel@tonic-gate for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL; 3490Sstevel@tonic-gate dtp = ldap_next_disptmpl( tmpllist, dtp )) { 3500Sstevel@tonic-gate for ( oclp = dtp->dt_oclist; oclp != NULLOCLIST; 3510Sstevel@tonic-gate oclp = oclp->oc_next ) { 3520Sstevel@tonic-gate needcnt = matchcnt = 0; 3530Sstevel@tonic-gate for ( i = 0; oclp->oc_objclasses[ i ] != NULL; ++i ) { 3540Sstevel@tonic-gate for ( j = 0; oclist[ j ] != NULL; ++j ) { 3550Sstevel@tonic-gate #ifdef SUN 3560Sstevel@tonic-gate /* LP@Sun : remove ending space from objectclass */ 3570Sstevel@tonic-gate right_trim(oclist[j]); 3580Sstevel@tonic-gate #endif 3590Sstevel@tonic-gate if ( strcasecmp( oclist[ j ], oclp->oc_objclasses[ i ] ) 3600Sstevel@tonic-gate == 0 ) { 3610Sstevel@tonic-gate ++matchcnt; 3620Sstevel@tonic-gate } 3630Sstevel@tonic-gate } 3640Sstevel@tonic-gate ++needcnt; 3650Sstevel@tonic-gate } 3660Sstevel@tonic-gate 3670Sstevel@tonic-gate if ( matchcnt == needcnt ) { 3680Sstevel@tonic-gate return( dtp ); 3690Sstevel@tonic-gate } 3700Sstevel@tonic-gate } 3710Sstevel@tonic-gate } 3720Sstevel@tonic-gate 3730Sstevel@tonic-gate return( NULLDISPTMPL ); 3740Sstevel@tonic-gate } 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate struct ldap_tmplitem * 3780Sstevel@tonic-gate ldap_first_tmplrow( struct ldap_disptmpl *tmpl ) 3790Sstevel@tonic-gate { 3800Sstevel@tonic-gate return( tmpl->dt_items ); 3810Sstevel@tonic-gate } 3820Sstevel@tonic-gate 3830Sstevel@tonic-gate 3840Sstevel@tonic-gate struct ldap_tmplitem * 3850Sstevel@tonic-gate ldap_next_tmplrow( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row ) 3860Sstevel@tonic-gate { 3870Sstevel@tonic-gate return( row == NULLTMPLITEM ? row : row->ti_next_in_col ); 3880Sstevel@tonic-gate } 3890Sstevel@tonic-gate 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate struct ldap_tmplitem * 3920Sstevel@tonic-gate ldap_first_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row ) 3930Sstevel@tonic-gate { 3940Sstevel@tonic-gate return( row ); 3950Sstevel@tonic-gate } 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate struct ldap_tmplitem * 3990Sstevel@tonic-gate ldap_next_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row, 4000Sstevel@tonic-gate struct ldap_tmplitem *col ) 4010Sstevel@tonic-gate { 4020Sstevel@tonic-gate return( col == NULLTMPLITEM ? col : col->ti_next_in_row ); 4030Sstevel@tonic-gate } 4040Sstevel@tonic-gate 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate char ** 4070Sstevel@tonic-gate ldap_tmplattrs( struct ldap_disptmpl *tmpl, char **includeattrs, 4080Sstevel@tonic-gate int exclude, unsigned int syntaxmask ) 4090Sstevel@tonic-gate { 4100Sstevel@tonic-gate /* 4110Sstevel@tonic-gate * this routine should filter out duplicate attributes... 4120Sstevel@tonic-gate */ 4130Sstevel@tonic-gate struct ldap_tmplitem *tirowp, *ticolp; 4140Sstevel@tonic-gate int i, attrcnt, memerr; 4150Sstevel@tonic-gate char **attrs; 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate attrcnt = 0; 4180Sstevel@tonic-gate memerr = 0; 4190Sstevel@tonic-gate 4200Sstevel@tonic-gate if (( attrs = (char **)malloc( sizeof( char * ))) == NULL ) { 4210Sstevel@tonic-gate return( NULL ); 4220Sstevel@tonic-gate } 4230Sstevel@tonic-gate 4240Sstevel@tonic-gate if ( includeattrs != NULL ) { 4250Sstevel@tonic-gate for ( i = 0; !memerr && includeattrs[ i ] != NULL; ++i ) { 4260Sstevel@tonic-gate if (( attrs = (char **)realloc( attrs, ( attrcnt + 2 ) * 4270Sstevel@tonic-gate sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] = 4280Sstevel@tonic-gate strdup( includeattrs[ i ] )) == NULL ) { 4290Sstevel@tonic-gate memerr = 1; 4300Sstevel@tonic-gate } else { 4310Sstevel@tonic-gate attrs[ attrcnt ] = NULL; 4320Sstevel@tonic-gate } 4330Sstevel@tonic-gate } 4340Sstevel@tonic-gate } 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate for ( tirowp = ldap_first_tmplrow( tmpl ); 4370Sstevel@tonic-gate !memerr && tirowp != NULLTMPLITEM; 4380Sstevel@tonic-gate tirowp = ldap_next_tmplrow( tmpl, tirowp )) { 4390Sstevel@tonic-gate for ( ticolp = ldap_first_tmplcol( tmpl, tirowp ); 4400Sstevel@tonic-gate ticolp != NULLTMPLITEM; 4410Sstevel@tonic-gate ticolp = ldap_next_tmplcol( tmpl, tirowp, ticolp )) { 4420Sstevel@tonic-gate 4430Sstevel@tonic-gate if ( syntaxmask != 0 ) { 4440Sstevel@tonic-gate if (( exclude && 4450Sstevel@tonic-gate ( syntaxmask & ticolp->ti_syntaxid ) != 0 ) || 4460Sstevel@tonic-gate ( !exclude && 4470Sstevel@tonic-gate ( syntaxmask & ticolp->ti_syntaxid ) == 0 )) { 4480Sstevel@tonic-gate continue; 4490Sstevel@tonic-gate } 4500Sstevel@tonic-gate } 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate if ( ticolp->ti_attrname != NULL ) { 4530Sstevel@tonic-gate if (( attrs = (char **)realloc( attrs, ( attrcnt + 2 ) * 4540Sstevel@tonic-gate sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] = 4550Sstevel@tonic-gate strdup( ticolp->ti_attrname )) == NULL ) { 4560Sstevel@tonic-gate memerr = 1; 4570Sstevel@tonic-gate } else { 4580Sstevel@tonic-gate attrs[ attrcnt ] = NULL; 4590Sstevel@tonic-gate } 4600Sstevel@tonic-gate } 4610Sstevel@tonic-gate } 4620Sstevel@tonic-gate } 4630Sstevel@tonic-gate 4640Sstevel@tonic-gate if ( memerr || attrcnt == 0 ) { 4650Sstevel@tonic-gate for ( i = 0; i < attrcnt; ++i ) { 4660Sstevel@tonic-gate if ( attrs[ i ] != NULL ) { 4670Sstevel@tonic-gate free( attrs[ i ] ); 4680Sstevel@tonic-gate } 4690Sstevel@tonic-gate } 4700Sstevel@tonic-gate 4710Sstevel@tonic-gate free( (char *)attrs ); 4720Sstevel@tonic-gate return( NULL ); 4730Sstevel@tonic-gate } 4740Sstevel@tonic-gate 4750Sstevel@tonic-gate return( attrs ); 4760Sstevel@tonic-gate } 4770Sstevel@tonic-gate 4780Sstevel@tonic-gate 4790Sstevel@tonic-gate static int 4800Sstevel@tonic-gate read_next_tmpl( char **bufp, ssize_t *blenp, struct ldap_disptmpl **tmplp, 4810Sstevel@tonic-gate int dtversion ) 4820Sstevel@tonic-gate { 4830Sstevel@tonic-gate int i, j, tokcnt, samerow, adsource; 4840Sstevel@tonic-gate char **toks, *itemopts; 4850Sstevel@tonic-gate struct ldap_disptmpl *tmpl; 4860Sstevel@tonic-gate struct ldap_oclist *ocp, *prevocp; 4870Sstevel@tonic-gate struct ldap_adddeflist *adp, *prevadp; 4880Sstevel@tonic-gate struct ldap_tmplitem *rowp, *ip, *previp; 4890Sstevel@tonic-gate 4900Sstevel@tonic-gate *tmplp = NULL; 4910Sstevel@tonic-gate 4920Sstevel@tonic-gate /* 4930Sstevel@tonic-gate * template name comes first 4940Sstevel@tonic-gate */ 4950Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { 4960Sstevel@tonic-gate free_strarray( toks ); 4970Sstevel@tonic-gate return( tokcnt == 0 ? 0 : LDAP_TMPL_ERR_SYNTAX ); 4980Sstevel@tonic-gate } 4990Sstevel@tonic-gate 5000Sstevel@tonic-gate if (( tmpl = (struct ldap_disptmpl *)calloc( (size_t) 1, 5010Sstevel@tonic-gate sizeof( struct ldap_disptmpl ))) == NULL ) { 5020Sstevel@tonic-gate free_strarray( toks ); 5030Sstevel@tonic-gate return( LDAP_TMPL_ERR_MEM ); 5040Sstevel@tonic-gate } 5050Sstevel@tonic-gate tmpl->dt_name = toks[ 0 ]; 5060Sstevel@tonic-gate free( (char *)toks ); 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate /* 5090Sstevel@tonic-gate * template plural name comes next 5100Sstevel@tonic-gate */ 5110Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { 5120Sstevel@tonic-gate free_strarray( toks ); 5130Sstevel@tonic-gate free_disptmpl( tmpl ); 5140Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 5150Sstevel@tonic-gate } 5160Sstevel@tonic-gate tmpl->dt_pluralname = toks[ 0 ]; 5170Sstevel@tonic-gate free( (char *)toks ); 5180Sstevel@tonic-gate 5190Sstevel@tonic-gate /* 5200Sstevel@tonic-gate * template icon name is next 5210Sstevel@tonic-gate */ 5220Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { 5230Sstevel@tonic-gate free_strarray( toks ); 5240Sstevel@tonic-gate free_disptmpl( tmpl ); 5250Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 5260Sstevel@tonic-gate } 5270Sstevel@tonic-gate tmpl->dt_iconname = toks[ 0 ]; 5280Sstevel@tonic-gate free( (char *)toks ); 5290Sstevel@tonic-gate 5300Sstevel@tonic-gate /* 5310Sstevel@tonic-gate * template options come next 5320Sstevel@tonic-gate */ 5330Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) < 1 ) { 5340Sstevel@tonic-gate free_strarray( toks ); 5350Sstevel@tonic-gate free_disptmpl( tmpl ); 5360Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 5370Sstevel@tonic-gate } 5380Sstevel@tonic-gate for ( i = 0; toks[ i ] != NULL; ++i ) { 5390Sstevel@tonic-gate for ( j = 0; tmploptions[ j ] != NULL; ++j ) { 5400Sstevel@tonic-gate if ( strcasecmp( toks[ i ], tmploptions[ j ] ) == 0 ) { 5410Sstevel@tonic-gate tmpl->dt_options |= tmploptvals[ j ]; 5420Sstevel@tonic-gate } 5430Sstevel@tonic-gate } 5440Sstevel@tonic-gate } 5450Sstevel@tonic-gate free_strarray( toks ); 5460Sstevel@tonic-gate 5470Sstevel@tonic-gate /* 5480Sstevel@tonic-gate * object class list is next 5490Sstevel@tonic-gate */ 5500Sstevel@tonic-gate while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) { 5510Sstevel@tonic-gate if (( ocp = (struct ldap_oclist *)calloc( (size_t) 1, 5520Sstevel@tonic-gate sizeof( struct ldap_oclist ))) == NULL ) { 5530Sstevel@tonic-gate free_strarray( toks ); 5540Sstevel@tonic-gate free_disptmpl( tmpl ); 5550Sstevel@tonic-gate return( LDAP_TMPL_ERR_MEM ); 5560Sstevel@tonic-gate } 5570Sstevel@tonic-gate ocp->oc_objclasses = toks; 5580Sstevel@tonic-gate if ( tmpl->dt_oclist == NULL ) { 5590Sstevel@tonic-gate tmpl->dt_oclist = ocp; 5600Sstevel@tonic-gate } else { 5610Sstevel@tonic-gate prevocp->oc_next = ocp; 5620Sstevel@tonic-gate } 5630Sstevel@tonic-gate prevocp = ocp; 5640Sstevel@tonic-gate } 5650Sstevel@tonic-gate if ( tokcnt < 0 ) { 5660Sstevel@tonic-gate free_disptmpl( tmpl ); 5670Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 5680Sstevel@tonic-gate } 5690Sstevel@tonic-gate 5700Sstevel@tonic-gate /* 5710Sstevel@tonic-gate * read name of attribute to authenticate as 5720Sstevel@tonic-gate */ 5730Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { 5740Sstevel@tonic-gate free_strarray( toks ); 5750Sstevel@tonic-gate free_disptmpl( tmpl ); 5760Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 5770Sstevel@tonic-gate } 5780Sstevel@tonic-gate if ( toks[ 0 ][ 0 ] != '\0' ) { 5790Sstevel@tonic-gate tmpl->dt_authattrname = toks[ 0 ]; 5800Sstevel@tonic-gate } else { 5810Sstevel@tonic-gate free( toks[ 0 ] ); 5820Sstevel@tonic-gate } 5830Sstevel@tonic-gate free( (char *)toks ); 5840Sstevel@tonic-gate 5850Sstevel@tonic-gate /* 5860Sstevel@tonic-gate * read default attribute to use for RDN 5870Sstevel@tonic-gate */ 5880Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { 5890Sstevel@tonic-gate free_strarray( toks ); 5900Sstevel@tonic-gate free_disptmpl( tmpl ); 5910Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 5920Sstevel@tonic-gate } 5930Sstevel@tonic-gate tmpl->dt_defrdnattrname = toks[ 0 ]; 5940Sstevel@tonic-gate free( (char *)toks ); 5950Sstevel@tonic-gate 5960Sstevel@tonic-gate /* 5970Sstevel@tonic-gate * read default location for new entries 5980Sstevel@tonic-gate */ 5990Sstevel@tonic-gate if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) { 6000Sstevel@tonic-gate free_strarray( toks ); 6010Sstevel@tonic-gate free_disptmpl( tmpl ); 6020Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 6030Sstevel@tonic-gate } 6040Sstevel@tonic-gate if ( toks[ 0 ][ 0 ] != '\0' ) { 6050Sstevel@tonic-gate tmpl->dt_defaddlocation = toks[ 0 ]; 6060Sstevel@tonic-gate } else { 6070Sstevel@tonic-gate free( toks[ 0 ] ); 6080Sstevel@tonic-gate } 6090Sstevel@tonic-gate free( (char *)toks ); 6100Sstevel@tonic-gate 6110Sstevel@tonic-gate /* 6120Sstevel@tonic-gate * read list of rules used to define default values for new entries 6130Sstevel@tonic-gate */ 6140Sstevel@tonic-gate while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) { 6150Sstevel@tonic-gate if ( strcasecmp( ADDEF_CONSTANT, toks[ 0 ] ) == 0 ) { 6160Sstevel@tonic-gate adsource = LDAP_ADSRC_CONSTANTVALUE; 6170Sstevel@tonic-gate } else if ( strcasecmp( ADDEF_ADDERSDN, toks[ 0 ] ) == 0 ) { 6180Sstevel@tonic-gate adsource = LDAP_ADSRC_ADDERSDN; 6190Sstevel@tonic-gate } else { 6200Sstevel@tonic-gate adsource = 0; 6210Sstevel@tonic-gate } 6220Sstevel@tonic-gate if ( adsource == 0 || tokcnt < 2 || 6230Sstevel@tonic-gate ( adsource == LDAP_ADSRC_CONSTANTVALUE && tokcnt != 3 ) || 6240Sstevel@tonic-gate ( adsource == LDAP_ADSRC_ADDERSDN && tokcnt != 2 )) { 6250Sstevel@tonic-gate free_strarray( toks ); 6260Sstevel@tonic-gate free_disptmpl( tmpl ); 6270Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 6280Sstevel@tonic-gate } 6290Sstevel@tonic-gate 6300Sstevel@tonic-gate if (( adp = (struct ldap_adddeflist *)calloc( (size_t) 1, 6310Sstevel@tonic-gate sizeof( struct ldap_adddeflist ))) == NULL ) { 6320Sstevel@tonic-gate free_strarray( toks ); 6330Sstevel@tonic-gate free_disptmpl( tmpl ); 6340Sstevel@tonic-gate return( LDAP_TMPL_ERR_MEM ); 6350Sstevel@tonic-gate } 6360Sstevel@tonic-gate adp->ad_source = adsource; 6370Sstevel@tonic-gate adp->ad_attrname = toks[ 1 ]; 6380Sstevel@tonic-gate if ( adsource == LDAP_ADSRC_CONSTANTVALUE ) { 6390Sstevel@tonic-gate adp->ad_value = toks[ 2 ]; 6400Sstevel@tonic-gate } 6410Sstevel@tonic-gate free( toks[ 0 ] ); 6420Sstevel@tonic-gate free( (char *)toks ); 6430Sstevel@tonic-gate 6440Sstevel@tonic-gate if ( tmpl->dt_adddeflist == NULL ) { 6450Sstevel@tonic-gate tmpl->dt_adddeflist = adp; 6460Sstevel@tonic-gate } else { 6470Sstevel@tonic-gate prevadp->ad_next = adp; 6480Sstevel@tonic-gate } 6490Sstevel@tonic-gate prevadp = adp; 6500Sstevel@tonic-gate } 6510Sstevel@tonic-gate 6520Sstevel@tonic-gate /* 6530Sstevel@tonic-gate * item list is next 6540Sstevel@tonic-gate */ 6550Sstevel@tonic-gate samerow = 0; 6560Sstevel@tonic-gate while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) { 6570Sstevel@tonic-gate if ( strcasecmp( toks[ 0 ], "item" ) == 0 ) { 6580Sstevel@tonic-gate if ( tokcnt < 4 ) { 6590Sstevel@tonic-gate free_strarray( toks ); 6600Sstevel@tonic-gate free_disptmpl( tmpl ); 6610Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 6620Sstevel@tonic-gate } 6630Sstevel@tonic-gate 6640Sstevel@tonic-gate if (( ip = (struct ldap_tmplitem *)calloc( (size_t) 1, 6650Sstevel@tonic-gate sizeof( struct ldap_tmplitem ))) == NULL ) { 6660Sstevel@tonic-gate free_strarray( toks ); 6670Sstevel@tonic-gate free_disptmpl( tmpl ); 6680Sstevel@tonic-gate return( LDAP_TMPL_ERR_MEM ); 6690Sstevel@tonic-gate } 6700Sstevel@tonic-gate 6710Sstevel@tonic-gate /* 6720Sstevel@tonic-gate * find syntaxid from config file string 6730Sstevel@tonic-gate */ 6740Sstevel@tonic-gate while (( itemopts = strrchr( toks[ 1 ], ',' )) != NULL ) { 6750Sstevel@tonic-gate *itemopts++ = '\0'; 6760Sstevel@tonic-gate for ( i = 0; itemoptions[ i ] != NULL; ++i ) { 6770Sstevel@tonic-gate if ( strcasecmp( itemopts, itemoptions[ i ] ) == 0 ) { 6780Sstevel@tonic-gate break; 6790Sstevel@tonic-gate } 6800Sstevel@tonic-gate } 6810Sstevel@tonic-gate if ( itemoptions[ i ] == NULL ) { 6820Sstevel@tonic-gate free_strarray( toks ); 6830Sstevel@tonic-gate free_disptmpl( tmpl ); 6840Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 6850Sstevel@tonic-gate } 6860Sstevel@tonic-gate ip->ti_options |= itemoptvals[ i ]; 6870Sstevel@tonic-gate } 6880Sstevel@tonic-gate 6890Sstevel@tonic-gate for ( i = 0; itemtypes[ i ] != NULL; ++i ) { 6900Sstevel@tonic-gate if ( strcasecmp( toks[ 1 ], itemtypes[ i ] ) == 0 ) { 6910Sstevel@tonic-gate break; 6920Sstevel@tonic-gate } 6930Sstevel@tonic-gate } 6940Sstevel@tonic-gate if ( itemtypes[ i ] == NULL ) { 6950Sstevel@tonic-gate free_strarray( toks ); 6960Sstevel@tonic-gate free_disptmpl( tmpl ); 6970Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 6980Sstevel@tonic-gate } 6990Sstevel@tonic-gate 7000Sstevel@tonic-gate free( toks[ 0 ] ); 7010Sstevel@tonic-gate free( toks[ 1 ] ); 7020Sstevel@tonic-gate ip->ti_syntaxid = itemsynids[ i ]; 7030Sstevel@tonic-gate ip->ti_label = toks[ 2 ]; 7040Sstevel@tonic-gate if ( toks[ 3 ][ 0 ] == '\0' ) { 7050Sstevel@tonic-gate ip->ti_attrname = NULL; 7060Sstevel@tonic-gate free( toks[ 3 ] ); 7070Sstevel@tonic-gate } else { 7080Sstevel@tonic-gate ip->ti_attrname = toks[ 3 ]; 7090Sstevel@tonic-gate } 7100Sstevel@tonic-gate if ( toks[ 4 ] != NULL ) { /* extra args. */ 7110Sstevel@tonic-gate for ( i = 0; toks[ i + 4 ] != NULL; ++i ) { 7120Sstevel@tonic-gate ; 7130Sstevel@tonic-gate } 7140Sstevel@tonic-gate if (( ip->ti_args = (char **) calloc( (size_t) (i + 1), sizeof( char * ))) 7150Sstevel@tonic-gate == NULL ) { 7160Sstevel@tonic-gate free_disptmpl( tmpl ); 7170Sstevel@tonic-gate return( LDAP_TMPL_ERR_MEM ); 7180Sstevel@tonic-gate } 7190Sstevel@tonic-gate for ( i = 0; toks[ i + 4 ] != NULL; ++i ) { 7200Sstevel@tonic-gate ip->ti_args[ i ] = toks[ i + 4 ]; 7210Sstevel@tonic-gate } 7220Sstevel@tonic-gate } 7230Sstevel@tonic-gate free( (char *)toks ); 7240Sstevel@tonic-gate 7250Sstevel@tonic-gate if ( tmpl->dt_items == NULL ) { 7260Sstevel@tonic-gate tmpl->dt_items = rowp = ip; 7270Sstevel@tonic-gate } else if ( samerow ) { 7280Sstevel@tonic-gate previp->ti_next_in_row = ip; 7290Sstevel@tonic-gate } else { 7300Sstevel@tonic-gate rowp->ti_next_in_col = ip; 7310Sstevel@tonic-gate rowp = ip; 7320Sstevel@tonic-gate } 7330Sstevel@tonic-gate previp = ip; 7340Sstevel@tonic-gate samerow = 0; 7350Sstevel@tonic-gate } else if ( strcasecmp( toks[ 0 ], "samerow" ) == 0 ) { 7360Sstevel@tonic-gate free_strarray( toks ); 7370Sstevel@tonic-gate samerow = 1; 7380Sstevel@tonic-gate } else { 7390Sstevel@tonic-gate free_strarray( toks ); 7400Sstevel@tonic-gate free_disptmpl( tmpl ); 7410Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 7420Sstevel@tonic-gate } 7430Sstevel@tonic-gate } 7440Sstevel@tonic-gate if ( tokcnt < 0 ) { 7450Sstevel@tonic-gate free_disptmpl( tmpl ); 7460Sstevel@tonic-gate return( LDAP_TMPL_ERR_SYNTAX ); 7470Sstevel@tonic-gate } 7480Sstevel@tonic-gate 7490Sstevel@tonic-gate *tmplp = tmpl; 7500Sstevel@tonic-gate return( 0 ); 7510Sstevel@tonic-gate } 752