root/source3/winbindd/nss_info.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nss_get_backend
  2. smb_register_idmap_nss
  3. parse_nss_parm
  4. nss_domain_list_add_domain
  5. nss_init
  6. find_nss_domain
  7. nss_get_info
  8. nss_map_to_alias
  9. nss_map_from_alias
  10. nss_close

   1 /*
   2    Unix SMB/CIFS implementation.
   3    Idmap NSS headers
   4 
   5    Copyright (C) Gerald Carter             2006
   6    Copyright (C) Michael Adam 2008
   7 
   8    This library is free software; you can redistribute it and/or
   9    modify it under the terms of the GNU Lesser General Public
  10    License as published by the Free Software Foundation; either
  11    version 3 of the License, or (at your option) any later version.
  12 
  13    This library is distributed in the hope that it will be useful,
  14    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16    Library General Public License for more details.
  17 
  18    You should have received a copy of the GNU Lesser General Public License
  19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21 
  22 #include "includes.h"
  23 #include "nss_info.h"
  24 
  25 static struct nss_function_entry *backends = NULL;
  26 static struct nss_function_entry *default_backend = NULL;
  27 static struct nss_domain_entry *nss_domain_list = NULL;
  28 
  29 /**********************************************************************
  30  Get idmap nss methods.
  31 **********************************************************************/
  32 
  33 static struct nss_function_entry *nss_get_backend(const char *name )
     /* [<][>][^][v][top][bottom][index][help] */
  34 {
  35         struct nss_function_entry *entry = backends;
  36 
  37         for(entry = backends; entry; entry = entry->next) {
  38                 if ( strequal(entry->name, name) )
  39                         return entry;
  40         }
  41 
  42         return NULL;
  43 }
  44 
  45 /*********************************************************************
  46  Allow a module to register itself as a backend.
  47 **********************************************************************/
  48 
  49  NTSTATUS smb_register_idmap_nss(int version, const char *name, struct nss_info_methods *methods)
     /* [<][>][^][v][top][bottom][index][help] */
  50 {
  51         struct nss_function_entry *entry;
  52 
  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;
  60         }
  61 
  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;
  65         }
  66 
  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;
  71         }
  72 
  73         entry = SMB_XMALLOC_P(struct nss_function_entry);
  74         entry->name = smb_xstrdup(name);
  75         entry->methods = methods;
  76 
  77         DLIST_ADD(backends, entry);
  78         DEBUG(5, ("smb_register_idmap_nss: Successfully added idmap "
  79                   "nss backend '%s'\n", name));
  80 
  81         return NT_STATUS_OK;
  82 }
  83 
  84 /********************************************************************
  85  *******************************************************************/
  86 
  87 static bool parse_nss_parm( const char *config, char **backend, char **domain )
     /* [<][>][^][v][top][bottom][index][help] */
  88 {
  89         char *p;
  90         char *q;
  91         int len;
  92 
  93         *backend = *domain = NULL;
  94 
  95         if ( !config )
  96                 return False;
  97 
  98         p = strchr( config, ':' );
  99 
 100         /* if no : then the string must be the backend name only */
 101 
 102         if ( !p ) {
 103                 *backend = SMB_STRDUP( config );
 104                 return (*backend != NULL);
 105         }
 106 
 107         /* split the string and return the two parts */
 108 
 109         if ( strlen(p+1) > 0 ) {
 110                 *domain = SMB_STRDUP( p+1 );
 111         }
 112 
 113         len = PTR_DIFF(p,config)+1;
 114         if ( (q = SMB_MALLOC_ARRAY( char, len )) == NULL ) {
 115                 SAFE_FREE( *backend );
 116                 return False;
 117         }
 118 
 119         StrnCpy( q, config, len-1);
 120         q[len-1] = '\0';
 121         *backend = q;
 122 
 123         return True;
 124 }
 125 
 126 static NTSTATUS nss_domain_list_add_domain(const char *domain,
     /* [<][>][^][v][top][bottom][index][help] */
 127                                            struct nss_function_entry *nss_backend)
 128 {
 129         struct nss_domain_entry *nss_domain;
 130 
 131         nss_domain = TALLOC_ZERO_P(nss_domain_list, struct nss_domain_entry);
 132         if (!nss_domain) {
 133                 DEBUG(0, ("nss_domain_list_add_domain: talloc() failure!\n"));
 134                 return NT_STATUS_NO_MEMORY;
 135         }
 136 
 137         nss_domain->backend = nss_backend;
 138         if (domain) {
 139                 nss_domain->domain  = talloc_strdup(nss_domain, domain);
 140                 if (!nss_domain->domain) {
 141                         DEBUG(0, ("nss_domain_list_add_domain: talloc() "
 142                                   "failure!\n"));
 143                         TALLOC_FREE(nss_domain);
 144                         return NT_STATUS_NO_MEMORY;
 145                 }
 146         }
 147 
 148         nss_domain->init_status = nss_domain->backend->methods->init(nss_domain);
 149         if (!NT_STATUS_IS_OK(nss_domain->init_status))  {
 150                 DEBUG(0, ("nss_init: Failed to init backend '%s' for domain "
 151                           "'%s'!\n", nss_backend->name, nss_domain->domain));
 152         }
 153 
 154         DLIST_ADD(nss_domain_list, nss_domain);
 155 
 156         DEBUG(10, ("Added domain '%s' with backend '%s' to nss_domain_list.\n",
 157                    domain, nss_backend->name));
 158 
 159         return NT_STATUS_OK;
 160 }
 161 
 162 /********************************************************************
 163  Each nss backend must not store global state, but rather be able
 164  to initialize the state on a per domain basis.
 165  *******************************************************************/
 166 
 167  NTSTATUS nss_init( const char **nss_list )
     /* [<][>][^][v][top][bottom][index][help] */
 168 {
 169         NTSTATUS status;
 170         static NTSTATUS nss_initialized = NT_STATUS_UNSUCCESSFUL;
 171         int i;
 172         char *backend, *domain;
 173         struct nss_function_entry *nss_backend;
 174 
 175         /* check for previous successful initializations */
 176 
 177         if ( NT_STATUS_IS_OK(nss_initialized) )
 178                 return NT_STATUS_OK;
 179 
 180         /* The "template" backend should alqays be registered as it
 181            is a static module */
 182 
 183         if ( (nss_backend = nss_get_backend( "template" )) == NULL ) {
 184                 static_init_nss_info;
 185         }
 186 
 187         /* Create the list of nss_domains (loading any shared plugins
 188            as necessary) */
 189 
 190         for ( i=0; nss_list && nss_list[i]; i++ ) {
 191 
 192                 if ( !parse_nss_parm(nss_list[i], &backend, &domain) ) {
 193                         DEBUG(0,("nss_init: failed to parse \"%s\"!\n",
 194                                  nss_list[i]));
 195                         continue;
 196                 }
 197 
 198                 DEBUG(10, ("parsed backend = '%s', domain = '%s'\n",
 199                            backend, domain));
 200 
 201                 /* validate the backend */
 202 
 203                 if ( (nss_backend = nss_get_backend( backend )) == NULL ) {
 204                         /* attempt to register the backend */
 205                         status = smb_probe_module( "nss_info", backend );
 206                         if ( !NT_STATUS_IS_OK(status) ) {
 207                                 continue;
 208                         }
 209 
 210                         /* try again */
 211                         if ( (nss_backend = nss_get_backend( backend )) == NULL ) {
 212                                 DEBUG(0,("nss_init: unregistered backend %s!.  Skipping\n",
 213                                          backend));
 214                                 continue;
 215                         }
 216                 }
 217 
 218                 /*
 219                  * The first config item of the list without an explicit domain
 220                  * is treated as the default nss info backend.
 221                  */
 222                 if ((domain == NULL) && (default_backend == NULL)) {
 223                         DEBUG(10, ("nss_init: using '%s' as default backend.\n",
 224                                    backend));
 225                         default_backend = nss_backend;
 226                 }
 227 
 228                 status = nss_domain_list_add_domain(domain, nss_backend);
 229                 if (!NT_STATUS_IS_OK(status)) {
 230                         return status;
 231                 }
 232 
 233                 /* cleanup */
 234 
 235                 SAFE_FREE( backend );
 236                 SAFE_FREE( domain );
 237         }
 238 
 239         if ( !nss_domain_list ) {
 240                 DEBUG(3,("nss_init: no nss backends configured.  "
 241                          "Defaulting to \"template\".\n"));
 242 
 243 
 244                 /* we shouild default to use template here */
 245         }
 246 
 247         nss_initialized = NT_STATUS_OK;
 248 
 249         return NT_STATUS_OK;
 250 }
 251 
 252 /********************************************************************
 253  *******************************************************************/
 254 
 255 static struct nss_domain_entry *find_nss_domain( const char *domain )
     /* [<][>][^][v][top][bottom][index][help] */
 256 {
 257         NTSTATUS status;
 258         struct nss_domain_entry *p;
 259 
 260         status = nss_init( lp_winbind_nss_info() );
 261         if ( !NT_STATUS_IS_OK(status) ) {
 262                 DEBUG(4,("nss_get_info: Failed to init nss_info API (%s)!\n",
 263                          nt_errstr(status)));
 264                 return NULL;
 265         }
 266 
 267         for ( p=nss_domain_list; p; p=p->next ) {
 268                 if ( strequal( p->domain, domain ) )
 269                         break;
 270         }
 271 
 272         /* If we didn't find a match, then use the default nss backend */
 273 
 274         if ( !p ) {
 275                 if (!default_backend) {
 276                         return NULL;
 277                 }
 278 
 279                 status = nss_domain_list_add_domain(domain, default_backend);
 280                 if (!NT_STATUS_IS_OK(status)) {
 281                         return NULL;
 282                 }
 283 
 284                 /*
 285                  * HACK ALERT:
 286                  * Here, we use the fact that the new domain was added at
 287                  * the beginning of the list...
 288                  */
 289                 p = nss_domain_list;
 290         }
 291 
 292         if ( !NT_STATUS_IS_OK( p->init_status ) ) {
 293                p->init_status = p->backend->methods->init( p );
 294         }
 295 
 296         return p;
 297 }
 298 
 299 /********************************************************************
 300  *******************************************************************/
 301 
 302  NTSTATUS nss_get_info( const char *domain, const DOM_SID *user_sid,
     /* [<][>][^][v][top][bottom][index][help] */
 303                        TALLOC_CTX *ctx,
 304                        ADS_STRUCT *ads, LDAPMessage *msg,
 305                        char **homedir, char **shell, char **gecos,
 306                        gid_t *p_gid)
 307 {
 308         struct nss_domain_entry *p;
 309         struct nss_info_methods *m;
 310 
 311         DEBUG(10, ("nss_get_info called for sid [%s] in domain '%s'\n",
 312                    sid_string_dbg(user_sid), domain?domain:"NULL"));
 313 
 314         if ( (p = find_nss_domain( domain )) == NULL ) {
 315                 DEBUG(4,("nss_get_info: Failed to find nss domain pointer for %s\n",
 316                          domain ));
 317                 return NT_STATUS_NOT_FOUND;
 318         }
 319 
 320         m = p->backend->methods;
 321 
 322         return m->get_nss_info( p, user_sid, ctx, ads, msg,
 323                                 homedir, shell, gecos, p_gid );
 324 }
 325 
 326 /********************************************************************
 327  *******************************************************************/
 328 
 329  NTSTATUS nss_map_to_alias( TALLOC_CTX *mem_ctx, const char *domain,
     /* [<][>][^][v][top][bottom][index][help] */
 330                             const char *name, char **alias )
 331 {
 332         struct nss_domain_entry *p;
 333         struct nss_info_methods *m;
 334 
 335         if ( (p = find_nss_domain( domain )) == NULL ) {
 336                 DEBUG(4,("nss_map_to_alias: Failed to find nss domain pointer for %s\n",
 337                          domain ));
 338                 return NT_STATUS_NOT_FOUND;
 339         }
 340 
 341         m = p->backend->methods;
 342 
 343         return m->map_to_alias(mem_ctx, p, name, alias);
 344 }
 345 
 346 
 347 /********************************************************************
 348  *******************************************************************/
 349 
 350  NTSTATUS nss_map_from_alias( TALLOC_CTX *mem_ctx, const char *domain,
     /* [<][>][^][v][top][bottom][index][help] */
 351                               const char *alias, char **name )
 352 {
 353         struct nss_domain_entry *p;
 354         struct nss_info_methods *m;
 355 
 356         if ( (p = find_nss_domain( domain )) == NULL ) {
 357                 DEBUG(4,("nss_map_from_alias: Failed to find nss domain pointer for %s\n",
 358                          domain ));
 359                 return NT_STATUS_NOT_FOUND;
 360         }
 361 
 362         m = p->backend->methods;
 363 
 364         return m->map_from_alias( mem_ctx, p, alias, name );
 365 }
 366 
 367 /********************************************************************
 368  *******************************************************************/
 369 
 370  NTSTATUS nss_close( const char *parameters )
     /* [<][>][^][v][top][bottom][index][help] */
 371 {
 372         struct nss_domain_entry *p = nss_domain_list;
 373         struct nss_domain_entry *q;
 374 
 375         while ( p && p->backend && p->backend->methods ) {
 376                 /* close the backend */
 377                 p->backend->methods->close_fn();
 378 
 379                 /* free the memory */
 380                 q = p;
 381                 p = p->next;
 382                 TALLOC_FREE( q );
 383         }
 384 
 385         return NT_STATUS_OK;
 386 }
 387 

/* [<][>][^][v][top][bottom][index][help] */