root/source3/lib/privileges.c

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

DEFINITIONS

This source file includes following definitions.
  1. get_privileges
  2. set_privileges
  3. get_privileges_for_sids
  4. priv_traverse_fn
  5. privilege_enumerate_accounts
  6. privilege_enum_sids
  7. grant_privilege
  8. grant_privilege_by_name
  9. revoke_privilege
  10. revoke_all_privileges
  11. revoke_privilege_by_name
  12. privilege_create_account
  13. privilege_delete_account
  14. privilege_set_init
  15. privilege_set_init_by_ctx
  16. privilege_set_free
  17. dup_luid_attr
  18. is_privileged_sid
  19. grant_all_privileges

   1 /*
   2    Unix SMB/CIFS implementation.
   3    Privileges handling functions
   4    Copyright (C) Jean François Micouleau       1998-2001
   5    Copyright (C) Simo Sorce                     2002-2003
   6    Copyright (C) Gerald (Jerry) Carter          2005
   7    Copyright (C) Michael Adam                   2007
   8 
   9    This program is free software; you can redistribute it and/or modify
  10    it under the terms of the GNU General Public License as published by
  11    the Free Software Foundation; either version 3 of the License, or
  12    (at your option) any later version.
  13 
  14    This program is distributed in the hope that it will be useful,
  15    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17    GNU General Public License for more details.
  18 
  19    You should have received a copy of the GNU General Public License
  20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  21 */
  22 
  23 
  24 #include "includes.h"
  25 
  26 #define PRIVPREFIX              "PRIV_"
  27 
  28 typedef struct {
  29         size_t count;
  30         DOM_SID *list;
  31 } SID_LIST;
  32 
  33 typedef struct {
  34         TALLOC_CTX *mem_ctx;
  35         SE_PRIV privilege;
  36         SID_LIST sids;
  37 } PRIV_SID_LIST;
  38 
  39 
  40 static bool get_privileges( const DOM_SID *sid, SE_PRIV *mask )
     /* [<][>][^][v][top][bottom][index][help] */
  41 {
  42         struct db_context *db = get_account_pol_db();
  43         fstring tmp, keystr;
  44         TDB_DATA data;
  45 
  46         /* Fail if the admin has not enable privileges */
  47 
  48         if ( !lp_enable_privileges() ) {
  49                 return False;
  50         }
  51 
  52         if ( db == NULL )
  53                 return False;
  54 
  55         /* PRIV_<SID> (NULL terminated) as the key */
  56 
  57         fstr_sprintf(keystr, "%s%s", PRIVPREFIX, sid_to_fstring(tmp, sid));
  58 
  59         data = dbwrap_fetch_bystring( db, talloc_tos(), keystr );
  60 
  61         if ( !data.dptr ) {
  62                 DEBUG(3, ("get_privileges: No privileges assigned to SID "
  63                           "[%s]\n", sid_string_dbg(sid)));
  64                 return False;
  65         }
  66 
  67         SMB_ASSERT( data.dsize == sizeof( SE_PRIV ) );
  68 
  69         se_priv_copy( mask, (SE_PRIV*)data.dptr );
  70         TALLOC_FREE(data.dptr);
  71 
  72         return True;
  73 }
  74 
  75 /***************************************************************************
  76  Store the privilege mask (set) for a given SID
  77 ****************************************************************************/
  78 
  79 static bool set_privileges( const DOM_SID *sid, SE_PRIV *mask )
     /* [<][>][^][v][top][bottom][index][help] */
  80 {
  81         struct db_context *db = get_account_pol_db();
  82         fstring tmp, keystr;
  83         TDB_DATA data;
  84 
  85         if ( !lp_enable_privileges() )
  86                 return False;
  87 
  88         if ( db == NULL )
  89                 return False;
  90 
  91         if ( !sid || (sid->num_auths == 0) ) {
  92                 DEBUG(0,("set_privileges: Refusing to store empty SID!\n"));
  93                 return False;
  94         }
  95 
  96         /* PRIV_<SID> (NULL terminated) as the key */
  97 
  98         fstr_sprintf(keystr, "%s%s", PRIVPREFIX, sid_to_fstring(tmp, sid));
  99 
 100         /* no packing.  static size structure, just write it out */
 101 
 102         data.dptr  = (uint8 *)mask;
 103         data.dsize = sizeof(SE_PRIV);
 104 
 105         return NT_STATUS_IS_OK(dbwrap_store_bystring(db, keystr, data,
 106                                                      TDB_REPLACE));
 107 }
 108 
 109 /*********************************************************************
 110  get a list of all privileges for all sids in the list
 111 *********************************************************************/
 112 
 113 bool get_privileges_for_sids(SE_PRIV *privileges, DOM_SID *slist, int scount)
     /* [<][>][^][v][top][bottom][index][help] */
 114 {
 115         SE_PRIV mask;
 116         int i;
 117         bool found = False;
 118 
 119         se_priv_copy( privileges, &se_priv_none );
 120 
 121         for ( i=0; i<scount; i++ ) {
 122                 /* don't add unless we actually have a privilege assigned */
 123 
 124                 if ( !get_privileges( &slist[i], &mask ) )
 125                         continue;
 126 
 127                 DEBUG(5,("get_privileges_for_sids: sid = %s\nPrivilege "
 128                          "set:\n", sid_string_dbg(&slist[i])));
 129                 dump_se_priv( DBGC_ALL, 5, &mask );
 130 
 131                 se_priv_add( privileges, &mask );
 132                 found = True;
 133         }
 134 
 135         return found;
 136 }
 137 
 138 
 139 /*********************************************************************
 140  traversal functions for privilege_enumerate_accounts
 141 *********************************************************************/
 142 
 143 static int priv_traverse_fn(struct db_record *rec, void *state)
     /* [<][>][^][v][top][bottom][index][help] */
 144 {
 145         PRIV_SID_LIST *priv = (PRIV_SID_LIST *)state;
 146         int  prefixlen = strlen(PRIVPREFIX);
 147         DOM_SID sid;
 148         fstring sid_string;
 149 
 150         /* easy check first */
 151 
 152         if (rec->value.dsize != sizeof(SE_PRIV) )
 153                 return 0;
 154 
 155         /* check we have a PRIV_+SID entry */
 156 
 157         if ( strncmp((char *)rec->key.dptr, PRIVPREFIX, prefixlen) != 0)
 158                 return 0;
 159 
 160         /* check to see if we are looking for a particular privilege */
 161 
 162         if ( !se_priv_equal(&priv->privilege, &se_priv_none) ) {
 163                 SE_PRIV mask;
 164 
 165                 se_priv_copy( &mask, (SE_PRIV*)rec->value.dptr );
 166 
 167                 /* if the SID does not have the specified privilege
 168                    then just return */
 169 
 170                 if ( !is_privilege_assigned( &mask, &priv->privilege) )
 171                         return 0;
 172         }
 173 
 174         fstrcpy( sid_string, (char *)&(rec->key.dptr[strlen(PRIVPREFIX)]) );
 175 
 176         /* this is a last ditch safety check to preventing returning
 177            and invalid SID (i've somehow run into this on development branches) */
 178 
 179         if ( strcmp( "S-0-0", sid_string ) == 0 )
 180                 return 0;
 181 
 182         if ( !string_to_sid(&sid, sid_string) ) {
 183                 DEBUG(0,("travsersal_fn_enum__acct: Could not convert SID [%s]\n",
 184                         sid_string));
 185                 return 0;
 186         }
 187 
 188         if (!NT_STATUS_IS_OK(add_sid_to_array(priv->mem_ctx, &sid,
 189                                               &priv->sids.list,
 190                                               &priv->sids.count)))
 191         {
 192                 return 0;
 193         }
 194 
 195         return 0;
 196 }
 197 
 198 /*********************************************************************
 199  Retreive list of privileged SIDs (for _lsa_enumerate_accounts()
 200 *********************************************************************/
 201 
 202 NTSTATUS privilege_enumerate_accounts(DOM_SID **sids, int *num_sids)
     /* [<][>][^][v][top][bottom][index][help] */
 203 {
 204         struct db_context *db = get_account_pol_db();
 205         PRIV_SID_LIST priv;
 206 
 207         if (db == NULL) {
 208                 return NT_STATUS_ACCESS_DENIED;
 209         }
 210 
 211         ZERO_STRUCT(priv);
 212 
 213         se_priv_copy( &priv.privilege, &se_priv_none );
 214 
 215         db->traverse_read(db, priv_traverse_fn, &priv);
 216 
 217         /* give the memory away; caller will free */
 218 
 219         *sids      = priv.sids.list;
 220         *num_sids  = priv.sids.count;
 221 
 222         return NT_STATUS_OK;
 223 }
 224 
 225 /*********************************************************************
 226  Retrieve list of SIDs granted a particular privilege
 227 *********************************************************************/
 228 
 229 NTSTATUS privilege_enum_sids(const SE_PRIV *mask, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 230                              DOM_SID **sids, int *num_sids)
 231 {
 232         struct db_context *db = get_account_pol_db();
 233         PRIV_SID_LIST priv;
 234 
 235         if (db == NULL) {
 236                 return NT_STATUS_ACCESS_DENIED;
 237         }
 238 
 239         ZERO_STRUCT(priv);
 240 
 241         se_priv_copy(&priv.privilege, mask);
 242         priv.mem_ctx = mem_ctx;
 243 
 244         db->traverse_read(db, priv_traverse_fn, &priv);
 245 
 246         /* give the memory away; caller will free */
 247 
 248         *sids      = priv.sids.list;
 249         *num_sids  = priv.sids.count;
 250 
 251         return NT_STATUS_OK;
 252 }
 253 
 254 /***************************************************************************
 255  Add privilege to sid
 256 ****************************************************************************/
 257 
 258 bool grant_privilege(const DOM_SID *sid, const SE_PRIV *priv_mask)
     /* [<][>][^][v][top][bottom][index][help] */
 259 {
 260         SE_PRIV old_mask, new_mask;
 261 
 262         ZERO_STRUCT( old_mask );
 263         ZERO_STRUCT( new_mask );
 264 
 265         if ( get_privileges( sid, &old_mask ) )
 266                 se_priv_copy( &new_mask, &old_mask );
 267         else
 268                 se_priv_copy( &new_mask, &se_priv_none );
 269 
 270         se_priv_add( &new_mask, priv_mask );
 271 
 272         DEBUG(10,("grant_privilege: %s\n", sid_string_dbg(sid)));
 273 
 274         DEBUGADD( 10, ("original privilege mask:\n"));
 275         dump_se_priv( DBGC_ALL, 10, &old_mask );
 276 
 277         DEBUGADD( 10, ("new privilege mask:\n"));
 278         dump_se_priv( DBGC_ALL, 10, &new_mask );
 279 
 280         return set_privileges( sid, &new_mask );
 281 }
 282 
 283 /*********************************************************************
 284  Add a privilege based on its name
 285 *********************************************************************/
 286 
 287 bool grant_privilege_by_name(DOM_SID *sid, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 288 {
 289         SE_PRIV mask;
 290 
 291         if (! se_priv_from_name(name, &mask)) {
 292                 DEBUG(3, ("grant_privilege_by_name: "
 293                           "No Such Privilege Found (%s)\n", name));
 294                 return False;
 295         }
 296 
 297         return grant_privilege( sid, &mask );
 298 }
 299 
 300 /***************************************************************************
 301  Remove privilege from sid
 302 ****************************************************************************/
 303 
 304 bool revoke_privilege(const DOM_SID *sid, const SE_PRIV *priv_mask)
     /* [<][>][^][v][top][bottom][index][help] */
 305 {
 306         SE_PRIV mask;
 307 
 308         /* if the user has no privileges, then we can't revoke any */
 309 
 310         if ( !get_privileges( sid, &mask ) )
 311                 return True;
 312 
 313         DEBUG(10,("revoke_privilege: %s\n", sid_string_dbg(sid)));
 314 
 315         DEBUGADD( 10, ("original privilege mask:\n"));
 316         dump_se_priv( DBGC_ALL, 10, &mask );
 317 
 318         se_priv_remove( &mask, priv_mask );
 319 
 320         DEBUGADD( 10, ("new privilege mask:\n"));
 321         dump_se_priv( DBGC_ALL, 10, &mask );
 322 
 323         return set_privileges( sid, &mask );
 324 }
 325 
 326 /*********************************************************************
 327  Revoke all privileges
 328 *********************************************************************/
 329 
 330 bool revoke_all_privileges( DOM_SID *sid )
     /* [<][>][^][v][top][bottom][index][help] */
 331 {
 332         return revoke_privilege( sid, &se_priv_all );
 333 }
 334 
 335 /*********************************************************************
 336  Add a privilege based on its name
 337 *********************************************************************/
 338 
 339 bool revoke_privilege_by_name(DOM_SID *sid, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 340 {
 341         SE_PRIV mask;
 342 
 343         if (! se_priv_from_name(name, &mask)) {
 344                 DEBUG(3, ("revoke_privilege_by_name: "
 345                           "No Such Privilege Found (%s)\n", name));
 346                 return False;
 347         }
 348 
 349         return revoke_privilege(sid, &mask);
 350 
 351 }
 352 
 353 /***************************************************************************
 354  Retrieve the SIDs assigned to a given privilege
 355 ****************************************************************************/
 356 
 357 NTSTATUS privilege_create_account(const DOM_SID *sid )
     /* [<][>][^][v][top][bottom][index][help] */
 358 {
 359         return ( grant_privilege(sid, &se_priv_none) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL);
 360 }
 361 
 362 /***************************************************************************
 363  Delete a privileged account
 364 ****************************************************************************/
 365 
 366 NTSTATUS privilege_delete_account(const struct dom_sid *sid)
     /* [<][>][^][v][top][bottom][index][help] */
 367 {
 368         struct db_context *db = get_account_pol_db();
 369         fstring tmp, keystr;
 370 
 371         if (!lp_enable_privileges()) {
 372                 return NT_STATUS_OK;
 373         }
 374 
 375         if (!db) {
 376                 return NT_STATUS_INVALID_HANDLE;
 377         }
 378 
 379         if (!sid || (sid->num_auths == 0)) {
 380                 return NT_STATUS_INVALID_SID;
 381         }
 382 
 383         /* PRIV_<SID> (NULL terminated) as the key */
 384 
 385         fstr_sprintf(keystr, "%s%s", PRIVPREFIX, sid_to_fstring(tmp, sid));
 386 
 387         return dbwrap_delete_bystring(db, keystr);
 388 }
 389 
 390 /****************************************************************************
 391  initialise a privilege list and set the talloc context
 392  ****************************************************************************/
 393 
 394 NTSTATUS privilege_set_init(PRIVILEGE_SET *priv_set)
     /* [<][>][^][v][top][bottom][index][help] */
 395 {
 396         TALLOC_CTX *mem_ctx;
 397 
 398         ZERO_STRUCTP( priv_set );
 399 
 400         mem_ctx = talloc_init("privilege set");
 401         if ( !mem_ctx ) {
 402                 DEBUG(0,("privilege_set_init: failed to initialize talloc ctx!\n"));
 403                 return NT_STATUS_NO_MEMORY;
 404         }
 405 
 406         priv_set->mem_ctx = mem_ctx;
 407 
 408         return NT_STATUS_OK;
 409 }
 410 
 411 /****************************************************************************
 412   initialise a privilege list and with someone else's talloc context
 413 ****************************************************************************/
 414 
 415 NTSTATUS privilege_set_init_by_ctx(TALLOC_CTX *mem_ctx, PRIVILEGE_SET *priv_set)
     /* [<][>][^][v][top][bottom][index][help] */
 416 {
 417         ZERO_STRUCTP( priv_set );
 418 
 419         priv_set->mem_ctx = mem_ctx;
 420         priv_set->ext_ctx = True;
 421 
 422         return NT_STATUS_OK;
 423 }
 424 
 425 /****************************************************************************
 426  Free all memory used by a PRIVILEGE_SET
 427 ****************************************************************************/
 428 
 429 void privilege_set_free(PRIVILEGE_SET *priv_set)
     /* [<][>][^][v][top][bottom][index][help] */
 430 {
 431         if ( !priv_set )
 432                 return;
 433 
 434         if ( !( priv_set->ext_ctx ) )
 435                 talloc_destroy( priv_set->mem_ctx );
 436 
 437         ZERO_STRUCTP( priv_set );
 438 }
 439 
 440 /****************************************************************************
 441  duplicate alloc luid_attr
 442  ****************************************************************************/
 443 
 444 NTSTATUS dup_luid_attr(TALLOC_CTX *mem_ctx, LUID_ATTR **new_la, LUID_ATTR *old_la, int count)
     /* [<][>][^][v][top][bottom][index][help] */
 445 {
 446         int i;
 447 
 448         if ( !old_la )
 449                 return NT_STATUS_OK;
 450 
 451         if (count) {
 452                 *new_la = TALLOC_ARRAY(mem_ctx, LUID_ATTR, count);
 453                 if ( !*new_la ) {
 454                         DEBUG(0,("dup_luid_attr: failed to alloc new LUID_ATTR array [%d]\n", count));
 455                         return NT_STATUS_NO_MEMORY;
 456                 }
 457         } else {
 458                 *new_la = NULL;
 459         }
 460 
 461         for (i=0; i<count; i++) {
 462                 (*new_la)[i].luid.high = old_la[i].luid.high;
 463                 (*new_la)[i].luid.low = old_la[i].luid.low;
 464                 (*new_la)[i].attr = old_la[i].attr;
 465         }
 466 
 467         return NT_STATUS_OK;
 468 }
 469 
 470 /*******************************************************************
 471 *******************************************************************/
 472 
 473 bool is_privileged_sid( const DOM_SID *sid )
     /* [<][>][^][v][top][bottom][index][help] */
 474 {
 475         SE_PRIV mask;
 476 
 477         return get_privileges( sid, &mask );
 478 }
 479 
 480 /*******************************************************************
 481 *******************************************************************/
 482 
 483 bool grant_all_privileges( const DOM_SID *sid )
     /* [<][>][^][v][top][bottom][index][help] */
 484 {
 485         SE_PRIV mask;
 486 
 487         if (!se_priv_put_all_privileges(&mask)) {
 488                 return False;
 489         }
 490 
 491         return grant_privilege( sid, &mask );
 492 }

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