summaryrefslogtreecommitdiff
path: root/source3/passdb
diff options
context:
space:
mode:
Diffstat (limited to 'source3/passdb')
-rw-r--r--source3/passdb/pdb_interface.c157
-rw-r--r--source3/passdb/pdb_tdb.c353
2 files changed, 510 insertions, 0 deletions
diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c
index 2005885c45..180db58c2d 100644
--- a/source3/passdb/pdb_interface.c
+++ b/source3/passdb/pdb_interface.c
@@ -587,6 +587,86 @@ static NTSTATUS context_delete_trust_passwd(struct pdb_context *context,
return trust->methods->delete_trust_passwd(trust->methods, trust);
}
+static NTSTATUS context_add_sid_to_privilege(struct pdb_context *context, const char *priv_name, const DOM_SID *sid)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
+ struct pdb_methods *curmethods;
+ if ((!context)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return ret;
+ }
+ curmethods = context->pdb_methods;
+ while (curmethods){
+ if (NT_STATUS_IS_OK(ret = curmethods->add_sid_to_privilege(curmethods, priv_name, sid))) {
+ return ret;
+ }
+ curmethods = curmethods->next;
+ }
+
+ return ret;
+}
+
+static NTSTATUS context_remove_sid_from_privilege(struct pdb_context *context, const char *priv_name, const DOM_SID *sid)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
+ struct pdb_methods *curmethods;
+ if ((!context)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return ret;
+ }
+ curmethods = context->pdb_methods;
+ while (curmethods){
+ if (NT_STATUS_IS_OK(ret = curmethods->remove_sid_from_privilege(curmethods, priv_name, sid))) {
+ return ret;
+ }
+ curmethods = curmethods->next;
+ }
+
+ return ret;
+}
+
+static NTSTATUS context_get_privilege_set(struct pdb_context *context, NT_USER_TOKEN *token, PRIVILEGE_SET *privset)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
+ struct pdb_methods *curmethods;
+ if ((!context)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return ret;
+ }
+ curmethods = context->pdb_methods;
+ while (curmethods){
+ if (NT_STATUS_IS_OK(ret = curmethods->get_privilege_set(curmethods, token, privset))) {
+ return ret;
+ }
+ curmethods = curmethods->next;
+ }
+
+ return ret;
+}
+
+static NTSTATUS context_get_privilege_entry(struct pdb_context *context, const char *privname, char **sid_list)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
+ struct pdb_methods *curmethods;
+ if ((!context)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return ret;
+ }
+ curmethods = context->pdb_methods;
+ while (curmethods){
+ if (NT_STATUS_IS_OK(ret = curmethods->get_privilege_entry(curmethods, privname, sid_list))) {
+ return ret;
+ }
+ curmethods = curmethods->next;
+ }
+
+ return ret;
+}
+
/******************************************************************
Free and cleanup a pdb context, any associated data and anything
that the attached modules might have associated.
@@ -711,6 +791,10 @@ static NTSTATUS make_pdb_context(struct pdb_context **context)
(*context)->pdb_add_trust_passwd = context_add_trust_passwd;
(*context)->pdb_update_trust_passwd = context_update_trust_passwd;
(*context)->pdb_delete_trust_passwd = context_delete_trust_passwd;
+ (*context)->pdb_add_sid_to_privilege = context_add_sid_to_privilege;
+ (*context)->pdb_remove_sid_from_privilege = context_remove_sid_from_privilege;
+ (*context)->pdb_get_privilege_set = context_get_privilege_set;
+ (*context)->pdb_get_privilege_entry = context_get_privilege_entry;
(*context)->free_fn = free_pdb_context;
@@ -1072,6 +1156,54 @@ BOOL pdb_enum_alias_memberships(const DOM_SID *sid,
aliases, num));
}
+BOOL pdb_add_sid_to_privilege(char *priv_name, DOM_SID *sid)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return NT_STATUS_IS_OK(pdb_context->
+ pdb_add_sid_to_privilege(pdb_context, priv_name, sid));
+}
+
+BOOL pdb_remove_sid_from_privilege(char *priv_name, DOM_SID *sid)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return NT_STATUS_IS_OK(pdb_context->
+ pdb_remove_sid_from_privilege(pdb_context, priv_name, sid));
+}
+
+BOOL pdb_get_privilege_set(NT_USER_TOKEN *token, PRIVILEGE_SET *privset)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return NT_STATUS_IS_OK(pdb_context->
+ pdb_get_privilege_set(pdb_context, token, privset));
+}
+
+BOOL pdb_get_privilege_entry(const char *privname, char **sid_list)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return NT_STATUS_IS_OK(pdb_context->
+ pdb_get_privilege_entry(pdb_context, privname, sid_list));
+}
+
/***************************************************************
Initialize the static context (at smbd startup etc).
@@ -1155,6 +1287,26 @@ static NTSTATUS pdb_default_delete_trust_passwd(struct pdb_methods *methods, con
return NT_STATUS_NOT_IMPLEMENTED;
}
+static NTSTATUS pdb_default_add_sid_to_privilege(struct pdb_methods *methods, const char *priv_name, const DOM_SID *sid)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS pdb_default_remove_sid_from_privilege(struct pdb_methods *methods, const char *priv_name, const DOM_SID *sid)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS pdb_default_get_privilege_set(struct pdb_methods *methods, NT_USER_TOKEN *token, PRIVILEGE_SET *privset)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS pdb_default_get_privilege_entry(struct pdb_methods *methods, const char *privname, char **sid_list)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
{
@@ -1193,5 +1345,10 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
(*methods)->update_trust_passwd = pdb_default_update_trust_passwd;
(*methods)->delete_trust_passwd = pdb_default_delete_trust_passwd;
+ (*methods)->add_sid_to_privilege = pdb_default_add_sid_to_privilege;
+ (*methods)->remove_sid_from_privilege = pdb_default_remove_sid_from_privilege;
+ (*methods)->get_privilege_set = pdb_default_get_privilege_set;
+ (*methods)->get_privilege_entry = pdb_default_get_privilege_entry;
+
return NT_STATUS_OK;
}
diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c
index f54463e158..39de791b07 100644
--- a/source3/passdb/pdb_tdb.c
+++ b/source3/passdb/pdb_tdb.c
@@ -42,6 +42,7 @@ static int tdbsam_debug_level = DBGC_ALL;
#define PASSDB_FILE_NAME "passdb.tdb"
#define USERPREFIX "USER_"
#define RIDPREFIX "RID_"
+#define PRIVPREFIX "PRIV_"
#define tdbsamver_t int32
struct tdbsam_privates {
@@ -895,6 +896,354 @@ static NTSTATUS tdbsam_delete_trust_passwd(struct pdb_methods *methods, const SA
}
+/***************************************************************************
+ Add sid to privilege
+****************************************************************************/
+
+static NTSTATUS tdbsam_add_sid_to_privilege(struct pdb_methods *my_methods, const char *priv_name, const DOM_SID *sid)
+{
+ struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
+ TDB_CONTEXT *pwd_tdb = NULL;
+ TDB_DATA key, data;
+ fstring keystr;
+ fstring name;
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ fstring sid_str;
+ char *sid_list = NULL, *s = NULL;
+ size_t str_size;
+ int flag;
+
+ /* invalidate the existing TDB iterator if it is open */
+
+ if (tdb_state->passwd_tdb) {
+ tdb_close(tdb_state->passwd_tdb);
+ tdb_state->passwd_tdb = NULL;
+ }
+
+ /* open the account TDB passwd*/
+
+ pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDWR | O_CREAT);
+
+ if (!pwd_tdb) {
+ DEBUG(0, ("tdb_add_sid_to_privilege: Unable to open TDB passwd (%s)!\n",
+ tdb_state->tdbsam_location));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* setup the PRIV index key */
+ fstrcpy(name, priv_name);
+ strlower_m(name);
+
+ slprintf(keystr, sizeof(keystr)-1, "%s%s", PRIVPREFIX, name);
+ key.dptr = keystr;
+ key.dsize = strlen(keystr) + 1;
+
+ /* check if the privilege already exist in the database */
+
+ /* get the record */
+ data = tdb_fetch (pwd_tdb, key);
+
+ if (data.dptr) {
+ /* check the list is not empty */
+ if (*(data.dptr)) {
+ sid_list = strdup(data.dptr);
+ if (!sid_list) {
+ DEBUG(0, ("tdbsam_add_sid_to_privilege: Out of Memory!\n"));
+ goto done;
+ }
+ }
+ SAFE_FREE(data.dptr);
+
+ flag = TDB_MODIFY;
+ } else {
+ /* if privilege does not exist create one */
+ flag = TDB_INSERT;
+ }
+
+ /* add the given sid */
+ sid_to_string(sid_str, sid);
+
+ if (sid_list) {
+ str_size = strlen(sid_list) + strlen(sid_str) + 2;
+ s = realloc(sid_list, str_size);
+ if (!s) {
+ DEBUG(0, ("tdbsam_add_sid_to_privilege: Out of Memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ sid_list = s;
+ s = &sid_list[strlen(sid_list)];
+ snprintf(s, strlen(sid_str) + 2, ",%s", sid_str);
+
+ } else {
+ sid_list = strdup(sid_str);
+ if (!sid_list) {
+ DEBUG(0, ("tdbsam_add_sid_to_privilege: Out of Memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ }
+
+ /* copy the PRIVILEGE struct into a BYTE buffer for storage */
+ data.dsize = strlen(sid_list) + 1;
+ data.dptr = sid_list;
+
+ /* add the account */
+ if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) {
+ DEBUG(0, ("Unable to modify passwd TDB!"));
+ DEBUGADD(0, (" Error: %s", tdb_errorstr(pwd_tdb)));
+ DEBUGADD(0, (" occured while storing the main record (%s)\n", keystr));
+ goto done;
+ }
+
+ ret = NT_STATUS_OK;
+
+done:
+ /* cleanup */
+ tdb_close (pwd_tdb);
+ SAFE_FREE(sid_list);
+
+ return (ret);
+}
+
+/***************************************************************************
+ Reomve sid to privilege
+****************************************************************************/
+
+static NTSTATUS tdbsam_remove_sid_from_privilege(struct pdb_methods *my_methods, const char *priv_name, const DOM_SID *sid)
+{
+ struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
+ TDB_CONTEXT *pwd_tdb = NULL;
+ TDB_DATA key, data;
+ fstring keystr;
+ fstring name;
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ fstring sid_str;
+ char *sid_list = NULL, *s = NULL;
+
+ /* invalidate the existing TDB iterator if it is open */
+
+ if (tdb_state->passwd_tdb) {
+ tdb_close(tdb_state->passwd_tdb);
+ tdb_state->passwd_tdb = NULL;
+ }
+
+ /* open the account TDB passwd*/
+
+ pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDWR | O_CREAT);
+
+ if (!pwd_tdb) {
+ DEBUG(0, ("tdbsam_remove_sid_from_privilege: Unable to open TDB passwd (%s)!\n",
+ tdb_state->tdbsam_location));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* setup the PRIV index key */
+ fstrcpy(name, priv_name);
+ strlower_m(name);
+
+ slprintf(keystr, sizeof(keystr)-1, "%s%s", PRIVPREFIX, name);
+ key.dptr = keystr;
+ key.dsize = strlen(keystr) + 1;
+
+ /* check if the privilege already exist in the database */
+
+ /* get the record */
+ data = tdb_fetch (pwd_tdb, key);
+
+ /* if privilege does not exist, just leave */
+ if (!data.dptr) {
+ ret = NT_STATUS_OK;
+ goto done;
+ }
+
+ if (data.dptr) {
+ sid_list = strdup(data.dptr);
+ if (!sid_list) {
+ DEBUG(0, ("tdbsam_remove_sid_from_privilege: Out of Memory!\n"));
+ goto done;
+ }
+ SAFE_FREE(data.dptr);
+ }
+
+ /* remove the given sid */
+ sid_to_string(sid_str, sid);
+
+ s = strstr(sid_list, sid_str);
+ if (s) {
+ char *p;
+ p = strstr(s, ",");
+ if (p) {
+ size_t l = strlen(sid_list) + 1 - (s - sid_list);
+ memmove(s, ++p, l);
+ } else {
+ if (s != sid_list)
+ s--;
+ *s = '\0';
+ }
+ } else {
+ /* sid not found */
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ /* copy the PRIVILEGE struct into a BYTE buffer for storage */
+ data.dsize = strlen(sid_list) + 1;
+ data.dptr = sid_list;
+
+ /* add the account */
+ if (tdb_store(pwd_tdb, key, data, TDB_MODIFY) != TDB_SUCCESS) {
+ DEBUG(0, ("Unable to modify passwd TDB!"));
+ DEBUGADD(0, (" Error: %s", tdb_errorstr(pwd_tdb)));
+ DEBUGADD(0, (" occured while storing the main record (%s)\n", keystr));
+ goto done;
+ }
+
+ ret = NT_STATUS_OK;
+
+done:
+ /* cleanup */
+ tdb_close (pwd_tdb);
+ SAFE_FREE(sid_list);
+
+ return (ret);
+}
+
+/***************************************************************************
+ get the privilege list for the given token
+****************************************************************************/
+
+struct priv_traverse {
+ char **sid_list;
+ PRIVILEGE_SET *privset;
+};
+
+static int tdbsam_traverse_privilege(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
+{
+ struct priv_traverse *pt = (struct priv_traverse *)state;
+ int prefixlen = strlen(PRIVPREFIX);
+
+ if (strncmp(key.dptr, PRIVPREFIX, prefixlen) == 0) {
+
+ /* add to privilege_set if any of the sid in the token
+ * is contained in the privilege */
+ int i;
+
+ for(i=0; pt->sid_list[i] != NULL; i++) {
+ char *c, *s;
+ int len;
+
+ s = data.dptr;
+ while (c = strchr(s, ',')) {
+ len = MAX((c - s), strlen(pt->sid_list[i]));
+ if (strncmp(s, pt->sid_list[i], len) == 0) {
+ DEBUG(10, ("sid [%s] found in users sid list\n", pt->sid_list[i]));
+ DEBUG(10, ("adding privilege [%s] to the users privilege list\n", &(key.dptr[prefixlen])));
+ add_privilege_by_name(pt->privset, &(key.dptr[prefixlen]));
+ return 0;
+ }
+ s = c + 1;
+ }
+ len = MAX(strlen(s), strlen(pt->sid_list[i]));
+ if (strncmp(s, pt->sid_list[i], len) == 0) {
+ DEBUG(10, ("sid [%s] found in users sid list\n", pt->sid_list[i]));
+ DEBUG(10, ("adding privilege [%s] to the users privilege list\n", &(key.dptr[prefixlen])));
+ add_privilege_by_name(pt->privset, &(key.dptr[prefixlen]));
+ return 0;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static NTSTATUS tdbsam_get_privilege_set(struct pdb_methods *my_methods, NT_USER_TOKEN *token, PRIVILEGE_SET *privset)
+{
+ struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ TDB_CONTEXT *pwd_tdb = NULL;
+ struct priv_traverse pt;
+ fstring sid_str;
+ char **sid_list;
+ int i;
+
+ if (!(pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDONLY )))
+ return NT_STATUS_UNSUCCESSFUL;
+
+ sid_list = (char **)malloc(sizeof(char *) * (token->num_sids + 1));
+ for (i = 0; i < token->num_sids; i++) {
+ sid_to_string(sid_str, &token->user_sids[i]);
+ sid_list[i] = strdup(sid_str);
+ if ( ! sid_list[i]) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ }
+ sid_list[i] = NULL;
+
+ pt.sid_list = sid_list;
+ pt.privset = privset;
+ tdb_traverse(pwd_tdb, tdbsam_traverse_privilege, &pt);
+
+ ret = NT_STATUS_OK;
+
+done:
+ i = 0;
+ while (sid_list[i]) {
+ free(sid_list[i]);
+ i++;
+ }
+ free(sid_list);
+
+ tdb_close(pwd_tdb);
+
+ return ret;
+}
+
+static NTSTATUS tdbsam_get_privilege_entry(struct pdb_methods *my_methods, const char *privname, char **sid_list)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ TDB_CONTEXT *pwd_tdb = NULL;
+ TDB_DATA key, data;
+ fstring name;
+ fstring keystr;
+
+ struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
+
+ if (!(pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDONLY)))
+ return ret;
+
+ /* setup the PRIV index key */
+ fstrcpy(name, privname);
+ strlower_m(name);
+
+ slprintf(keystr, sizeof(keystr)-1, "%s%s", PRIVPREFIX, name);
+ key.dptr = keystr;
+ key.dsize = strlen(keystr) + 1;
+
+ data = tdb_fetch(pwd_tdb, key);
+ if (!data.dptr)
+ goto done;
+
+ *sid_list = strdup(data.dptr);
+ SAFE_FREE(data.dptr);
+
+ if (!*sid_list)
+ goto done;
+
+ ret = NT_STATUS_OK;
+done:
+ tdb_close(pwd_tdb);
+ return ret;
+}
+
+
+
+
+
+
+
static NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
{
NTSTATUS nt_status;
@@ -919,6 +1268,10 @@ static NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_meth
(*pdb_method)->add_trust_passwd = tdbsam_add_trust_passwd;
(*pdb_method)->update_trust_passwd = tdbsam_update_trust_passwd;
(*pdb_method)->delete_trust_passwd = tdbsam_delete_trust_passwd;
+ (*pdb_method)->add_sid_to_privilege = tdbsam_add_sid_to_privilege;
+ (*pdb_method)->remove_sid_from_privilege = tdbsam_remove_sid_from_privilege;
+ (*pdb_method)->get_privilege_set = tdbsam_get_privilege_set;
+ (*pdb_method)->get_privilege_entry = tdbsam_get_privilege_entry;
tdb_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct tdbsam_privates));