root/source3/libsmb/samlogon_cache.c

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

DEFINITIONS

This source file includes following definitions.
  1. netsamlogon_cache_init
  2. netsamlogon_cache_shutdown
  3. netsamlogon_clear_cached_user
  4. netsamlogon_cache_store
  5. netsamlogon_cache_get
  6. netsamlogon_cache_have

   1 /*
   2    Unix SMB/CIFS implementation.
   3    Net_sam_logon info3 helpers
   4    Copyright (C) Alexander Bokovoy              2002.
   5    Copyright (C) Andrew Bartlett                2002.
   6    Copyright (C) Gerald Carter                  2003.
   7    Copyright (C) Tim Potter                     2003.
   8    Copyright (C) Guenther Deschner              2008.
   9 
  10    This program is free software; you can redistribute it and/or modify
  11    it under the terms of the GNU General Public License as published by
  12    the Free Software Foundation; either version 3 of the License, or
  13    (at your option) any later version.
  14 
  15    This program is distributed in the hope that it will be useful,
  16    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18    GNU General Public License for more details.
  19 
  20    You should have received a copy of the GNU General Public License
  21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  22 */
  23 
  24 #include "includes.h"
  25 #include "librpc/gen_ndr/ndr_krb5pac.h"
  26 
  27 #define NETSAMLOGON_TDB "netsamlogon_cache.tdb"
  28 
  29 static TDB_CONTEXT *netsamlogon_tdb = NULL;
  30 
  31 /***********************************************************************
  32  open the tdb
  33  ***********************************************************************/
  34 
  35 bool netsamlogon_cache_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
  36 {
  37         if (!netsamlogon_tdb) {
  38                 netsamlogon_tdb = tdb_open_log(cache_path(NETSAMLOGON_TDB), 0,
  39                                                TDB_DEFAULT, O_RDWR | O_CREAT, 0600);
  40         }
  41 
  42         return (netsamlogon_tdb != NULL);
  43 }
  44 
  45 
  46 /***********************************************************************
  47  Shutdown samlogon_cache database
  48 ***********************************************************************/
  49 
  50 bool netsamlogon_cache_shutdown(void)
     /* [<][>][^][v][top][bottom][index][help] */
  51 {
  52         if (netsamlogon_tdb) {
  53                 return (tdb_close(netsamlogon_tdb) == 0);
  54         }
  55 
  56         return true;
  57 }
  58 
  59 /***********************************************************************
  60  Clear cache getpwnam and getgroups entries from the winbindd cache
  61 ***********************************************************************/
  62 
  63 void netsamlogon_clear_cached_user(struct netr_SamInfo3 *info3)
     /* [<][>][^][v][top][bottom][index][help] */
  64 {
  65         DOM_SID user_sid;
  66         fstring keystr, tmp;
  67 
  68         if (!info3) {
  69                 return;
  70         }
  71 
  72         if (!netsamlogon_cache_init()) {
  73                 DEBUG(0,("netsamlogon_clear_cached_user: cannot open "
  74                         "%s for write!\n",
  75                         NETSAMLOGON_TDB));
  76                 return;
  77         }
  78         sid_copy(&user_sid, info3->base.domain_sid);
  79         sid_append_rid(&user_sid, info3->base.rid);
  80 
  81         /* Prepare key as DOMAIN-SID/USER-RID string */
  82         slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, &user_sid));
  83 
  84         DEBUG(10,("netsamlogon_clear_cached_user: SID [%s]\n", keystr));
  85 
  86         tdb_delete_bystring(netsamlogon_tdb, keystr);
  87 }
  88 
  89 /***********************************************************************
  90  Store a netr_SamInfo3 structure in a tdb for later user
  91  username should be in UTF-8 format
  92 ***********************************************************************/
  93 
  94 bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3)
     /* [<][>][^][v][top][bottom][index][help] */
  95 {
  96         TDB_DATA data;
  97         fstring keystr, tmp;
  98         bool result = false;
  99         DOM_SID user_sid;
 100         time_t t = time(NULL);
 101         TALLOC_CTX *mem_ctx;
 102         DATA_BLOB blob;
 103         enum ndr_err_code ndr_err;
 104         struct netsamlogoncache_entry r;
 105 
 106         if (!info3) {
 107                 return false;
 108         }
 109 
 110         if (!netsamlogon_cache_init()) {
 111                 DEBUG(0,("netsamlogon_cache_store: cannot open %s for write!\n",
 112                         NETSAMLOGON_TDB));
 113                 return false;
 114         }
 115 
 116         sid_copy(&user_sid, info3->base.domain_sid);
 117         sid_append_rid(&user_sid, info3->base.rid);
 118 
 119         /* Prepare key as DOMAIN-SID/USER-RID string */
 120         slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, &user_sid));
 121 
 122         DEBUG(10,("netsamlogon_cache_store: SID [%s]\n", keystr));
 123 
 124         /* Prepare data */
 125 
 126         if (!(mem_ctx = TALLOC_P( NULL, int))) {
 127                 DEBUG(0,("netsamlogon_cache_store: talloc() failed!\n"));
 128                 return false;
 129         }
 130 
 131         /* only Samba fills in the username, not sure why NT doesn't */
 132         /* so we fill it in since winbindd_getpwnam() makes use of it */
 133 
 134         if (!info3->base.account_name.string) {
 135                 info3->base.account_name.string = talloc_strdup(info3, username);
 136         }
 137 
 138         r.timestamp = t;
 139         r.info3 = *info3;
 140 
 141         if (DEBUGLEVEL >= 10) {
 142                 NDR_PRINT_DEBUG(netsamlogoncache_entry, &r);
 143         }
 144 
 145         ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &r,
 146                                        (ndr_push_flags_fn_t)ndr_push_netsamlogoncache_entry);
 147         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 148                 DEBUG(0,("netsamlogon_cache_store: failed to push entry to cache\n"));
 149                 TALLOC_FREE(mem_ctx);
 150                 return false;
 151         }
 152 
 153         data.dsize = blob.length;
 154         data.dptr = blob.data;
 155 
 156         if (tdb_store_bystring(netsamlogon_tdb, keystr, data, TDB_REPLACE) != -1) {
 157                 result = true;
 158         }
 159 
 160         TALLOC_FREE(mem_ctx);
 161 
 162         return result;
 163 }
 164 
 165 /***********************************************************************
 166  Retrieves a netr_SamInfo3 structure from a tdb.  Caller must
 167  free the user_info struct (malloc()'d memory)
 168 ***********************************************************************/
 169 
 170 struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid)
     /* [<][>][^][v][top][bottom][index][help] */
 171 {
 172         struct netr_SamInfo3 *info3 = NULL;
 173         TDB_DATA data;
 174         fstring keystr, tmp;
 175         enum ndr_err_code ndr_err;
 176         DATA_BLOB blob;
 177         struct netsamlogoncache_entry r;
 178 
 179         if (!netsamlogon_cache_init()) {
 180                 DEBUG(0,("netsamlogon_cache_get: cannot open %s for write!\n",
 181                         NETSAMLOGON_TDB));
 182                 return false;
 183         }
 184 
 185         /* Prepare key as DOMAIN-SID/USER-RID string */
 186         slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, user_sid));
 187         DEBUG(10,("netsamlogon_cache_get: SID [%s]\n", keystr));
 188         data = tdb_fetch_bystring( netsamlogon_tdb, keystr );
 189 
 190         if (!data.dptr) {
 191                 return NULL;
 192         }
 193 
 194         info3 = TALLOC_ZERO_P(mem_ctx, struct netr_SamInfo3);
 195         if (!info3) {
 196                 goto done;
 197         }
 198 
 199         blob = data_blob_const(data.dptr, data.dsize);
 200 
 201         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &r,
 202                                       (ndr_pull_flags_fn_t)ndr_pull_netsamlogoncache_entry);
 203 
 204         if (DEBUGLEVEL >= 10) {
 205                 NDR_PRINT_DEBUG(netsamlogoncache_entry, &r);
 206         }
 207 
 208         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 209                 DEBUG(0,("netsamlogon_cache_get: failed to pull entry from cache\n"));
 210                 tdb_delete(netsamlogon_tdb, data);
 211                 TALLOC_FREE(info3);
 212                 goto done;
 213         }
 214 
 215         info3 = (struct netr_SamInfo3 *)talloc_memdup(mem_ctx, &r.info3,
 216                                                       sizeof(r.info3));
 217 
 218  done:
 219         SAFE_FREE(data.dptr);
 220 
 221         return info3;
 222 
 223 #if 0   /* The netsamlogon cache needs to hang around.  Something about
 224            this feels wrong, but it is the only way we can get all of the
 225            groups.  The old universal groups cache didn't expire either.
 226            --jerry */
 227         {
 228                 time_t          now = time(NULL);
 229                 uint32          time_diff;
 230 
 231                 /* is the entry expired? */
 232                 time_diff = now - t;
 233 
 234                 if ( (time_diff < 0 ) || (time_diff > lp_winbind_cache_time()) ) {
 235                         DEBUG(10,("netsamlogon_cache_get: cache entry expired \n"));
 236                         tdb_delete( netsamlogon_tdb, key );
 237                         TALLOC_FREE( user );
 238                 }
 239         }
 240 #endif
 241 }
 242 
 243 bool netsamlogon_cache_have(const DOM_SID *user_sid)
     /* [<][>][^][v][top][bottom][index][help] */
 244 {
 245         TALLOC_CTX *mem_ctx = talloc_init("netsamlogon_cache_have");
 246         struct netr_SamInfo3 *info3 = NULL;
 247         bool result;
 248 
 249         if (!mem_ctx)
 250                 return False;
 251 
 252         info3 = netsamlogon_cache_get(mem_ctx, user_sid);
 253 
 254         result = (info3 != NULL);
 255 
 256         talloc_destroy(mem_ctx);
 257 
 258         return result;
 259 }

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