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 Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 3 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 Lesser General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 static struct nss_function_entry
*backends
= NULL
;
25 static struct nss_domain_entry
*nss_domain_list
= NULL
;
27 /**********************************************************************
28 Get idmap nss methods.
29 **********************************************************************/
31 static struct nss_function_entry
*nss_get_backend(const char *name
)
33 struct nss_function_entry
*entry
= backends
;
35 for(entry
= backends
; entry
; entry
= entry
->next
) {
36 if ( strequal(entry
->name
, name
) )
43 /*********************************************************************
44 Allow a module to register itself as a backend.
45 **********************************************************************/
47 NTSTATUS
smb_register_idmap_nss(int version
, const char *name
, struct nss_info_methods
*methods
)
49 struct nss_function_entry
*entry
;
51 if ((version
!= SMB_NSS_INFO_INTERFACE_VERSION
)) {
52 DEBUG(0, ("smb_register_idmap_nss: Failed to register idmap_nss module.\n"
53 "The module was compiled against SMB_NSS_INFO_INTERFACE_VERSION %d,\n"
54 "current SMB_NSS_INFO_INTERFACE_VERSION is %d.\n"
55 "Please recompile against the current version of samba!\n",
56 version
, SMB_NSS_INFO_INTERFACE_VERSION
));
57 return NT_STATUS_OBJECT_TYPE_MISMATCH
;
60 if (!name
|| !name
[0] || !methods
) {
61 DEBUG(0,("smb_register_idmap_nss: called with NULL pointer or empty name!\n"));
62 return NT_STATUS_INVALID_PARAMETER
;
65 if ( nss_get_backend(name
) ) {
66 DEBUG(0,("smb_register_idmap_nss: idmap module %s "
67 "already registered!\n", name
));
68 return NT_STATUS_OBJECT_NAME_COLLISION
;
71 entry
= SMB_XMALLOC_P(struct nss_function_entry
);
72 entry
->name
= smb_xstrdup(name
);
73 entry
->methods
= methods
;
75 DLIST_ADD(backends
, entry
);
76 DEBUG(5, ("smb_register_idmap_nss: Successfully added idmap "
77 "nss backend '%s'\n", name
));
82 /********************************************************************
83 *******************************************************************/
85 static bool parse_nss_parm( const char *config
, char **backend
, char **domain
)
91 *backend
= *domain
= NULL
;
96 p
= strchr( config
, ':' );
98 /* if no : then the string must be the backend name only */
101 *backend
= SMB_STRDUP( config
);
102 return (*backend
!= NULL
);
105 /* split the string and return the two parts */
107 if ( strlen(p
+1) > 0 ) {
108 *domain
= SMB_STRDUP( p
+1 );
111 len
= PTR_DIFF(p
,config
)+1;
112 if ( (q
= SMB_MALLOC_ARRAY( char, len
)) == NULL
) {
113 SAFE_FREE( *backend
);
117 StrnCpy( q
, config
, len
-1);
124 /********************************************************************
125 Each nss backend must not store global state, but rather be able
126 to initialize the state on a per domain basis.
127 *******************************************************************/
129 NTSTATUS
nss_init( const char **nss_list
)
132 static NTSTATUS nss_initialized
= NT_STATUS_UNSUCCESSFUL
;
134 char *backend
, *domain
;
135 struct nss_function_entry
*nss_backend
;
136 struct nss_domain_entry
*nss_domain
;
138 /* check for previous successful initializations */
140 if ( NT_STATUS_IS_OK(nss_initialized
) )
143 /* The "template" backend should alqays be registered as it
144 is a static module */
146 if ( (nss_backend
= nss_get_backend( "template" )) == NULL
) {
147 static_init_nss_info
;
150 /* Create the list of nss_domains (loading any shared plugins
153 for ( i
=0; nss_list
&& nss_list
[i
]; i
++ ) {
155 if ( !parse_nss_parm(nss_list
[i
], &backend
, &domain
) ) {
156 DEBUG(0,("nss_init: failed to parse \"%s\"!\n",
161 /* validate the backend */
163 if ( (nss_backend
= nss_get_backend( backend
)) == NULL
) {
164 /* attempt to register the backend */
165 status
= smb_probe_module( "nss_info", backend
);
166 if ( !NT_STATUS_IS_OK(status
) ) {
171 if ( (nss_backend
= nss_get_backend( backend
)) == NULL
) {
172 DEBUG(0,("nss_init: unregistered backend %s!. Skipping\n",
179 /* fill in the nss_domain_entry and add it to the
182 nss_domain
= TALLOC_ZERO_P( nss_domain_list
, struct nss_domain_entry
);
184 DEBUG(0,("nss_init: talloc() failure!\n"));
185 return NT_STATUS_NO_MEMORY
;
188 nss_domain
->backend
= nss_backend
;
189 nss_domain
->domain
= talloc_strdup( nss_domain
, domain
);
191 /* Try to init and ave the result */
193 nss_domain
->init_status
= nss_domain
->backend
->methods
->init( nss_domain
);
194 DLIST_ADD( nss_domain_list
, nss_domain
);
195 if ( !NT_STATUS_IS_OK(nss_domain
->init_status
) ) {
196 DEBUG(0,("nss_init: Failed to init backend for %s domain!\n",
197 nss_domain
->domain
));
202 SAFE_FREE( backend
);
206 if ( !nss_domain_list
) {
207 DEBUG(3,("nss_init: no nss backends configured. "
208 "Defaulting to \"template\".\n"));
211 /* we shouild default to use template here */
215 nss_initialized
= NT_STATUS_OK
;
220 /********************************************************************
221 *******************************************************************/
223 static struct nss_domain_entry
*find_nss_domain( const char *domain
)
226 struct nss_domain_entry
*p
;
228 status
= nss_init( lp_winbind_nss_info() );
229 if ( !NT_STATUS_IS_OK(status
) ) {
230 DEBUG(4,("nss_get_info: Failed to init nss_info API (%s)!\n",
235 for ( p
=nss_domain_list
; p
; p
=p
->next
) {
236 if ( strequal( p
->domain
, domain
) )
240 /* If we didn't find a match, then use the default nss info */
243 if ( !nss_domain_list
) {
250 if ( !NT_STATUS_IS_OK( p
->init_status
) ) {
251 p
->init_status
= p
->backend
->methods
->init( p
);
257 /********************************************************************
258 *******************************************************************/
260 NTSTATUS
nss_get_info( const char *domain
, const DOM_SID
*user_sid
,
262 ADS_STRUCT
*ads
, LDAPMessage
*msg
,
263 char **homedir
, char **shell
, char **gecos
,
266 struct nss_domain_entry
*p
;
267 struct nss_info_methods
*m
;
269 if ( (p
= find_nss_domain( domain
)) == NULL
) {
270 DEBUG(4,("nss_get_info: Failed to find nss domain pointer for %s\n",
272 return NT_STATUS_NOT_FOUND
;
275 m
= p
->backend
->methods
;
277 return m
->get_nss_info( p
, user_sid
, ctx
, ads
, msg
,
278 homedir
, shell
, gecos
, p_gid
);
281 /********************************************************************
282 *******************************************************************/
284 NTSTATUS
nss_close( const char *parameters
)
286 struct nss_domain_entry
*p
= nss_domain_list
;
287 struct nss_domain_entry
*q
;
289 while ( p
&& p
->backend
&& p
->backend
->methods
) {
290 /* close the backend */
291 p
->backend
->methods
->close_fn();
293 /* free the memory */