2 Unix SMB/CIFS implementation.
5 Copyright (C) Gerald Carter 2006
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with this library; if not, write to the
19 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
26 static struct nss_function_entry
*backends
= NULL
;
27 static struct nss_domain_entry
*nss_domain_list
= NULL
;
29 /**********************************************************************
30 Get idmap nss methods.
31 **********************************************************************/
33 static struct nss_function_entry
*nss_get_backend(const char *name
)
35 struct nss_function_entry
*entry
= backends
;
37 for(entry
= backends
; entry
; entry
= entry
->next
) {
38 if ( strequal(entry
->name
, name
) )
45 /*********************************************************************
46 Allow a module to register itself as a backend.
47 **********************************************************************/
49 NTSTATUS
smb_register_idmap_nss(int version
, const char *name
, struct nss_info_methods
*methods
)
51 struct nss_function_entry
*entry
;
53 if ((version
!= SMB_NSS_INFO_INTERFACE_VERSION
)) {
54 DEBUG(0, ("smb_register_idmap_nss: Failed to register idmap_nss module.\n"
55 "The module was compiled against SMB_NSS_INFO_INTERFACE_VERSION %d,\n"
56 "current SMB_NSS_INFO_INTERFACE_VERSION is %d.\n"
57 "Please recompile against the current version of samba!\n",
58 version
, SMB_NSS_INFO_INTERFACE_VERSION
));
59 return NT_STATUS_OBJECT_TYPE_MISMATCH
;
62 if (!name
|| !name
[0] || !methods
) {
63 DEBUG(0,("smb_register_idmap_nss: called with NULL pointer or empty name!\n"));
64 return NT_STATUS_INVALID_PARAMETER
;
67 if ( nss_get_backend(name
) ) {
68 DEBUG(0,("smb_register_idmap_nss: idmap module %s "
69 "already registered!\n", name
));
70 return NT_STATUS_OBJECT_NAME_COLLISION
;
73 entry
= SMB_XMALLOC_P(struct nss_function_entry
);
74 entry
->name
= smb_xstrdup(name
);
75 entry
->methods
= methods
;
77 DLIST_ADD(backends
, entry
);
78 DEBUG(5, ("smb_register_idmap_nss: Successfully added idmap "
79 "nss backend '%s'\n", name
));
84 /********************************************************************
85 *******************************************************************/
87 static BOOL
parse_nss_parm( const char *config
, char **backend
, char **domain
)
93 *backend
= *domain
= NULL
;
98 p
= strchr( config
, ':' );
100 /* if no : then the string must be the backend name only */
103 *backend
= SMB_STRDUP( config
);
104 return (*backend
!= NULL
);
107 /* split the string and return the two parts */
109 if ( strlen(p
+1) > 0 ) {
110 *domain
= SMB_STRDUP( p
+1 );
113 len
= PTR_DIFF(p
,config
)+1;
114 if ( (q
= SMB_MALLOC_ARRAY( char, len
)) == NULL
) {
115 SAFE_FREE( *backend
);
119 StrnCpy( q
, config
, len
-1);
126 /********************************************************************
127 Each nss backend must not store global state, but rather be able
128 to initialize the state on a per domain basis.
129 *******************************************************************/
131 NTSTATUS
nss_init( const char **nss_list
)
134 static NTSTATUS nss_initialized
= NT_STATUS_UNSUCCESSFUL
;
136 char *backend
, *domain
;
137 struct nss_function_entry
*nss_backend
;
138 struct nss_domain_entry
*nss_domain
;
140 /* check for previous successful initializations */
142 if ( NT_STATUS_IS_OK(nss_initialized
) )
145 /* The "template" backend should alqays be registered as it
146 is a static module */
148 if ( (nss_backend
= nss_get_backend( "template" )) == NULL
) {
149 static_init_nss_info
;
152 /* Create the list of nss_domains (loading any shared plugins
155 for ( i
=0; nss_list
&& nss_list
[i
]; i
++ ) {
157 if ( !parse_nss_parm(nss_list
[i
], &backend
, &domain
) ) {
158 DEBUG(0,("nss_init: failed to parse \"%s\"!\n",
163 /* validate the backend */
165 if ( (nss_backend
= nss_get_backend( backend
)) == NULL
) {
166 /* attempt to register the backend */
167 status
= smb_probe_module( "nss_info", backend
);
168 if ( !NT_STATUS_IS_OK(status
) ) {
173 if ( (nss_backend
= nss_get_backend( backend
)) == NULL
) {
174 DEBUG(0,("nss_init: unregistered backend %s!. Skipping\n",
181 /* fill in the nss_domain_entry and add it to the
184 nss_domain
= TALLOC_ZERO_P( nss_domain_list
, struct nss_domain_entry
);
186 DEBUG(0,("nss_init: talloc() failure!\n"));
187 return NT_STATUS_NO_MEMORY
;
190 nss_domain
->backend
= nss_backend
;
191 nss_domain
->domain
= talloc_strdup( nss_domain
, domain
);
193 status
= nss_domain
->backend
->methods
->init( nss_domain
);
194 if ( NT_STATUS_IS_OK( status
) ) {
195 DLIST_ADD( nss_domain_list
, nss_domain
);
197 DEBUG(0,("nss_init: Failed to init backend for %s domain!\n",
198 nss_domain
->domain
));
203 SAFE_FREE( backend
);
207 if ( !nss_domain_list
) {
208 DEBUG(3,("nss_init: no nss backends configured. "
209 "Defaulting to \"template\".\n"));
212 /* we shouild default to use template here */
216 nss_initialized
= NT_STATUS_OK
;
221 /********************************************************************
222 *******************************************************************/
224 static struct nss_domain_entry
*find_nss_domain( const char *domain
)
227 struct nss_domain_entry
*p
;
229 status
= nss_init( lp_winbind_nss_info() );
230 if ( !NT_STATUS_IS_OK(status
) ) {
231 DEBUG(4,("nss_get_info: Failed to init nss_info API (%s)!\n",
236 for ( p
=nss_domain_list
; p
; p
=p
->next
) {
237 if ( strequal( p
->domain
, domain
) )
241 /* If we didn't find a match, then use the default nss info */
244 if ( !nss_domain_list
) {
254 /********************************************************************
255 *******************************************************************/
257 NTSTATUS
nss_get_info( const char *domain
, const DOM_SID
*user_sid
,
259 ADS_STRUCT
*ads
, LDAPMessage
*msg
,
260 char **homedir
, char **shell
, char **gecos
,
263 struct nss_domain_entry
*p
;
264 struct nss_info_methods
*m
;
266 if ( (p
= find_nss_domain( domain
)) == NULL
) {
267 DEBUG(4,("nss_get_info: Failed to find nss domain pointer for %s\n",
269 return NT_STATUS_NOT_FOUND
;
272 m
= p
->backend
->methods
;
274 return m
->get_nss_info( p
, user_sid
, ctx
, ads
, msg
,
275 homedir
, shell
, gecos
, p_gid
);
278 /********************************************************************
279 *******************************************************************/
281 NTSTATUS
nss_close( const char *parameters
)
283 struct nss_domain_entry
*p
= nss_domain_list
;
284 struct nss_domain_entry
*q
;
286 while ( p
&& p
->backend
&& p
->backend
->methods
) {
287 /* close the backend */
288 p
->backend
->methods
->close_fn();
290 /* free the memory */