s3-passdb: Python wrapper for passdb
authorAmitay Isaacs <amitay@gmail.com>
Mon, 15 Aug 2011 07:21:38 +0000 (17:21 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 19 Aug 2011 06:34:57 +0000 (16:34 +1000)
- Added Groupmap python wrapper
- Added passdb methods

   getgrsid, getgrgid, getgrnam
   create_dom_group, delete_dom_group
   add_group_mapping_entry, update_group_mapping_entry, delete_group_mapping_entry
   enum_group_mapping, enum_group_members
   add_groupmem, del_groupmem
   create_alias, delete_alias
   get_aliasinfo, set_aliasinfo
   add_aliasmem, del_aliasmem, enum_aliasmem
   get_account_policy, set_account_policy
   search_groups, search_aliases

Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
source3/passdb/py_passdb.c

index 30c3f8ccc93724a27ba754000c627b734d9aaa52..2b3ac5211051fd15bc68743f39bbbb25a4bd4ee7 100644 (file)
@@ -46,6 +46,7 @@ static PyTypeObject *dom_sid_Type = NULL;
 static PyTypeObject *guid_Type = NULL;
 
 staticforward PyTypeObject PySamu;
+staticforward PyTypeObject PyGroupmap;
 staticforward PyTypeObject PyPDB;
 
 static PyObject *py_pdb_error;
@@ -949,13 +950,189 @@ static PyObject *py_samu_new(PyTypeObject *type, PyObject *args, PyObject *kwarg
 }
 
 static PyTypeObject PySamu = {
-       .tp_name = "passdb.samu",
+       .tp_name = "passdb.Samu",
        .tp_basicsize = sizeof(pytalloc_Object),
        .tp_getset = py_samu_getsetters,
        .tp_methods = NULL,
        .tp_new = py_samu_new,
        .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
-       .tp_doc = "samu() -> samu object\n",
+       .tp_doc = "Samu() -> samu object\n",
+};
+
+
+static PyObject *py_groupmap_get_gid(PyObject *obj, void *closure)
+{
+       GROUP_MAP *group_map = (GROUP_MAP *)pytalloc_get_ptr(obj);
+       PyObject *py_gid;
+
+       py_gid = PyInt_FromLong(group_map->gid);
+       return py_gid;
+}
+
+static int py_groupmap_set_gid(PyObject *obj, PyObject *value, void *closure)
+{
+       GROUP_MAP *group_map = (GROUP_MAP *)pytalloc_get_ptr(obj);
+
+       PY_CHECK_TYPE(&PyInt_Type, value, return -1;);
+       group_map->gid = PyInt_AsLong(value);
+       return 0;
+}
+
+static PyObject *py_groupmap_get_sid(PyObject *obj, void *closure)
+{
+       GROUP_MAP *group_map = (GROUP_MAP *)pytalloc_get_ptr(obj);
+       PyObject *py_sid;
+       struct dom_sid *group_sid;
+       TALLOC_CTX *mem_ctx;
+
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       group_sid = dom_sid_dup(mem_ctx, &group_map->sid);
+       if (group_sid == NULL) {
+               PyErr_NoMemory();
+               talloc_free(mem_ctx);
+               return NULL;
+       }
+
+       py_sid = pytalloc_steal(dom_sid_Type, group_sid);
+
+       talloc_free(mem_ctx);
+
+       return py_sid;
+}
+
+static int py_groupmap_set_sid(PyObject *obj, PyObject *value, void *closure)
+{
+       GROUP_MAP *group_map = (GROUP_MAP *)pytalloc_get_ptr(obj);
+
+       PY_CHECK_TYPE(dom_sid_Type, value, return -1;);
+       group_map->sid = *pytalloc_get_type(value, struct dom_sid);
+       return 0;
+}
+
+static PyObject *py_groupmap_get_sid_name_use(PyObject *obj, void *closure)
+{
+       GROUP_MAP *group_map = (GROUP_MAP *)pytalloc_get_ptr(obj);
+       PyObject *py_sid_name_use;
+
+       py_sid_name_use = PyInt_FromLong(group_map->sid_name_use);
+       return py_sid_name_use;
+}
+
+static int py_groupmap_set_sid_name_use(PyObject *obj, PyObject *value, void *closure)
+{
+       GROUP_MAP *group_map = (GROUP_MAP *)pytalloc_get_ptr(obj);
+
+       PY_CHECK_TYPE(&PyInt_Type, value, return -1;);
+       group_map->sid_name_use = PyInt_AsLong(value);
+       return 0;
+}
+
+static PyObject *py_groupmap_get_nt_name(PyObject *obj, void *closure)
+{
+       GROUP_MAP *group_map = (GROUP_MAP *)pytalloc_get_ptr(obj);
+       PyObject *py_nt_name;
+       if (group_map->nt_name == NULL) {
+               py_nt_name = Py_None;
+               Py_INCREF(py_nt_name);
+       } else {
+               py_nt_name = PyString_FromString(group_map->nt_name);
+       }
+       return py_nt_name;
+}
+
+static int py_groupmap_set_nt_name(PyObject *obj, PyObject *value, void *closure)
+{
+       GROUP_MAP *group_map = (GROUP_MAP *)pytalloc_get_ptr(obj);
+
+       PY_CHECK_TYPE(&PyString_Type, value, return -1;);
+       if (value == Py_None) {
+               fstrcpy(group_map->nt_name, NULL);
+       } else {
+               fstrcpy(group_map->nt_name, PyString_AsString(value));
+       }
+       return 0;
+}
+
+static PyObject *py_groupmap_get_comment(PyObject *obj, void *closure)
+{
+       GROUP_MAP *group_map = (GROUP_MAP *)pytalloc_get_ptr(obj);
+       PyObject *py_comment;
+       if (group_map->comment == NULL) {
+               py_comment = Py_None;
+               Py_INCREF(py_comment);
+       } else {
+               py_comment = PyString_FromString(group_map->comment);
+       }
+       return py_comment;
+}
+
+static int py_groupmap_set_comment(PyObject *obj, PyObject *value, void *closure)
+{
+       GROUP_MAP *group_map = (GROUP_MAP *)pytalloc_get_ptr(obj);
+
+       PY_CHECK_TYPE(&PyString_Type, value, return -1;);
+       if (value == Py_None) {
+               fstrcpy(group_map->comment, NULL);
+       } else {
+               fstrcpy(group_map->comment, PyString_AsString(value));
+       }
+       return 0;
+}
+
+static PyGetSetDef py_groupmap_getsetters[] = {
+       { discard_const_p(char, "gid"), py_groupmap_get_gid, py_groupmap_set_gid },
+       { discard_const_p(char, "sid"), py_groupmap_get_sid, py_groupmap_set_sid },
+       { discard_const_p(char, "sid_name_use"), py_groupmap_get_sid_name_use, py_groupmap_set_sid_name_use },
+       { discard_const_p(char, "nt_name"), py_groupmap_get_nt_name, py_groupmap_set_nt_name },
+       { discard_const_p(char, "comment"), py_groupmap_get_comment, py_groupmap_set_comment },
+       { NULL }
+};
+
+static PyObject *py_groupmap_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+       GROUP_MAP *group_map;
+       TALLOC_CTX *mem_ctx;
+       PyObject *py_group_map;
+
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       group_map = talloc_zero(mem_ctx, GROUP_MAP);
+       if (group_map == NULL) {
+               PyErr_NoMemory();
+               talloc_free(mem_ctx);
+               return NULL;
+       }
+
+       py_group_map = pytalloc_steal(type, group_map);
+       if (py_group_map == NULL) {
+               PyErr_NoMemory();
+               talloc_free(mem_ctx);
+               return NULL;
+       }
+
+       talloc_free(mem_ctx);
+
+       return py_group_map;
+}
+
+
+static PyTypeObject PyGroupmap = {
+       .tp_name = "passdb.Groupmap",
+       .tp_basicsize = sizeof(pytalloc_Object),
+       .tp_getset = py_groupmap_getsetters,
+       .tp_methods = NULL,
+       .tp_new = py_groupmap_new,
+       .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+       .tp_doc = "Groupmap() -> group map object\n",
 };
 
 
@@ -975,53 +1152,949 @@ static PyObject *py_pdb_domain_info(pytalloc_Object *self, PyObject *args)
                return NULL;
        }
 
-       domain_info = methods->get_domain_info(methods, tframe);
-       if (! domain_info) {
-               Py_RETURN_NONE;
-       }
+       domain_info = methods->get_domain_info(methods, tframe);
+       if (! domain_info) {
+               Py_RETURN_NONE;
+       }
+
+       sid = dom_sid_dup(tframe, &domain_info->sid);
+       if (sid == NULL) {
+               PyErr_NoMemory();
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       guid = talloc(tframe, struct GUID);
+       if (guid == NULL) {
+               PyErr_NoMemory();
+               talloc_free(tframe);
+               return NULL;
+       }
+       *guid = domain_info->guid;
+
+       if ((py_domain_info = PyDict_New()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       PyDict_SetItemString(py_domain_info, "name", PyString_FromString(domain_info->name));
+       PyDict_SetItemString(py_domain_info, "dns_domain", PyString_FromString(domain_info->name));
+       PyDict_SetItemString(py_domain_info, "dns_forest", PyString_FromString(domain_info->name));
+       PyDict_SetItemString(py_domain_info, "dom_sid", pytalloc_steal(dom_sid_Type, sid));
+       PyDict_SetItemString(py_domain_info, "guid", pytalloc_steal(guid_Type, guid));
+
+       talloc_free(tframe);
+
+       return py_domain_info;
+}
+
+
+static PyObject *py_pdb_getsampwnam(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       const char *username;
+       struct pdb_methods *methods;
+       struct samu *sam_acct;
+       PyObject *py_sam_acct;
+       TALLOC_CTX *tframe;
+
+       if (!PyArg_ParseTuple(args, "s:getsampwnam", &username)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       py_sam_acct = py_samu_new(&PySamu, NULL, NULL);
+       if (py_sam_acct == NULL) {
+               PyErr_NoMemory();
+               talloc_free(tframe);
+               return NULL;
+       }
+       sam_acct = (struct samu *)pytalloc_get_ptr(py_sam_acct);
+
+       status = methods->getsampwnam(methods, sam_acct, username);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to get user information for '%s', (%d,%s)",
+                               username,
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               Py_DECREF(py_sam_acct);
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       talloc_free(tframe);
+       return py_sam_acct;
+}
+
+static PyObject *py_pdb_getsampwsid(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       struct samu *sam_acct;
+       PyObject *py_sam_acct;
+       TALLOC_CTX *tframe;
+       PyObject *py_user_sid;
+
+       if (!PyArg_ParseTuple(args, "O:getsampwsid", &py_user_sid)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       py_sam_acct = py_samu_new(&PySamu, NULL, NULL);
+       if (py_sam_acct == NULL) {
+               PyErr_NoMemory();
+               talloc_free(tframe);
+               return NULL;
+       }
+       sam_acct = (struct samu *)pytalloc_get_ptr(py_sam_acct);
+
+       status = methods->getsampwsid(methods, sam_acct, pytalloc_get_ptr(py_user_sid));
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to get user information from SID, (%d,%s)",
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               Py_DECREF(py_sam_acct);
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       talloc_free(tframe);
+       return py_sam_acct;
+}
+
+static PyObject *py_pdb_create_user(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       const char *username;
+       unsigned int acct_flags;
+       unsigned int rid;
+       TALLOC_CTX *tframe;
+
+       if (!PyArg_ParseTuple(args, "sI:create_user", &username, &acct_flags)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       status = methods->create_user(methods, tframe, username, acct_flags, &rid);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to create user (%s), (%d,%s)",
+                               username,
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       talloc_free(tframe);
+       return PyInt_FromLong(rid);
+}
+
+static PyObject *py_pdb_delete_user(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       TALLOC_CTX *tframe;
+       struct samu *sam_acct;
+       PyObject *py_sam_acct;
+
+       if (!PyArg_ParseTuple(args, "O!:delete_user", &PySamu, &py_sam_acct)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       sam_acct = pytalloc_get_ptr(py_sam_acct);
+
+       status = methods->delete_user(methods, tframe, sam_acct);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to delete user, (%d,%s)",
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       talloc_free(tframe);
+       Py_RETURN_NONE;
+}
+
+static PyObject *py_pdb_add_sam_account(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       TALLOC_CTX *tframe;
+       struct samu *sam_acct;
+       PyObject *py_sam_acct;
+
+       if (!PyArg_ParseTuple(args, "O!:add_sam_account", &PySamu, &py_sam_acct)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       sam_acct = pytalloc_get_ptr(py_sam_acct);
+
+       status = methods->add_sam_account(methods, sam_acct);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to add sam account, (%d,%s)",
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       talloc_free(tframe);
+       Py_RETURN_NONE;
+}
+
+static PyObject *py_pdb_update_sam_account(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       TALLOC_CTX *tframe;
+       struct samu *sam_acct;
+       PyObject *py_sam_acct;
+
+       if (!PyArg_ParseTuple(args, "O!:update_sam_account", &PySamu, &py_sam_acct)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       sam_acct = pytalloc_get_ptr(py_sam_acct);
+
+       status = methods->update_sam_account(methods, sam_acct);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to update sam account, (%d,%s)",
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       talloc_free(tframe);
+       Py_RETURN_NONE;
+}
+
+static PyObject *py_pdb_delete_sam_account(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       TALLOC_CTX *tframe;
+       struct samu *sam_acct;
+       PyObject *py_sam_acct;
+
+       if (!PyArg_ParseTuple(args, "O!:delete_sam_account", &PySamu, &py_sam_acct)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       sam_acct = pytalloc_get_ptr(py_sam_acct);
+
+       status = methods->delete_sam_account(methods, sam_acct);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to delete sam account, (%d,%s)",
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       talloc_free(tframe);
+       Py_RETURN_NONE;
+}
+
+static PyObject *py_pdb_rename_sam_account(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       TALLOC_CTX *tframe;
+       struct samu *sam_acct;
+       const char *new_username;
+       PyObject *py_sam_acct;
+
+       if (!PyArg_ParseTuple(args, "O!s:rename_sam_account", &PySamu, &py_sam_acct,
+                                       &new_username)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       sam_acct = pytalloc_get_ptr(py_sam_acct);
+
+       status = methods->rename_sam_account(methods, sam_acct, new_username);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to rename sam account, (%d,%s)",
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       talloc_free(tframe);
+       Py_RETURN_NONE;
+}
+
+
+static PyObject *py_pdb_getgrsid(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       TALLOC_CTX *tframe;
+       GROUP_MAP *group_map;
+       struct dom_sid *domain_sid;
+       PyObject *py_domain_sid, *py_group_map;
+
+       if (!PyArg_ParseTuple(args, "O!:getgrsid", dom_sid_Type, &py_domain_sid)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       domain_sid = pytalloc_get_ptr(py_domain_sid);
+
+       py_group_map = py_groupmap_new(&PyGroupmap, NULL, NULL);
+       if (py_group_map == NULL) {
+               PyErr_NoMemory();
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       group_map = pytalloc_get_ptr(py_group_map);
+
+       status = methods->getgrsid(methods, group_map, *domain_sid);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to get group information by sid, (%d,%s)",
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       talloc_free(tframe);
+       return py_group_map;
+}
+
+
+static PyObject *py_pdb_getgrgid(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       TALLOC_CTX *tframe;
+       GROUP_MAP *group_map;
+       PyObject *py_group_map;
+       unsigned int gid_value;
+
+       if (!PyArg_ParseTuple(args, "I:getgrgid", &gid_value)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       py_group_map = py_groupmap_new(&PyGroupmap, NULL, NULL);
+       if (py_group_map == NULL) {
+               PyErr_NoMemory();
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       group_map = pytalloc_get_ptr(py_group_map);
+
+       status = methods->getgrgid(methods, group_map, gid_value);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to get group information by gid, (%d,%s)",
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       talloc_free(tframe);
+       return py_group_map;
+}
+
+
+static PyObject *py_pdb_getgrnam(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       TALLOC_CTX *tframe;
+       GROUP_MAP *group_map;
+       PyObject *py_group_map;
+       const char *groupname;
+
+       if (!PyArg_ParseTuple(args, "s:getgrnam", &groupname)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       py_group_map = py_groupmap_new(&PyGroupmap, NULL, NULL);
+       if (py_group_map == NULL) {
+               PyErr_NoMemory();
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       group_map = pytalloc_get_ptr(py_group_map);
+
+       status = methods->getgrnam(methods, group_map, groupname);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to get group information by name, (%d,%s)",
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       talloc_free(tframe);
+       return py_group_map;
+}
+
+
+static PyObject *py_pdb_create_dom_group(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       TALLOC_CTX *tframe;
+       const char *groupname;
+       uint32_t group_rid;
+
+       if (!PyArg_ParseTuple(args, "s:create_dom_group", &groupname)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       status = methods->create_dom_group(methods, tframe, groupname, &group_rid);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to create domain group (%s), (%d,%s)",
+                               groupname,
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       talloc_free(tframe);
+       return PyInt_FromLong(group_rid);
+}
+
+
+static PyObject *py_pdb_delete_dom_group(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       TALLOC_CTX *tframe;
+       unsigned int group_rid;
+
+       if (!PyArg_ParseTuple(args, "I:delete_dom_group", &group_rid)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       status = methods->delete_dom_group(methods, tframe, group_rid);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to delete domain group (rid=%d), (%d,%s)",
+                               group_rid,
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       talloc_free(tframe);
+       Py_RETURN_NONE;
+}
+
+
+static PyObject *py_pdb_add_group_mapping_entry(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       TALLOC_CTX *tframe;
+       PyObject *py_group_map;
+       GROUP_MAP *group_map;
+
+       if (!PyArg_ParseTuple(args, "O!:add_group_mapping_entry", &PyGroupmap, &py_group_map)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       group_map = pytalloc_get_ptr(py_group_map);
+
+       status = methods->add_group_mapping_entry(methods, group_map);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to add group mapping entry, (%d,%s)",
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       talloc_free(tframe);
+       Py_RETURN_NONE;
+}
+
+
+static PyObject *py_pdb_update_group_mapping_entry(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       TALLOC_CTX *tframe;
+       PyObject *py_group_map;
+       GROUP_MAP *group_map;
+
+       if (!PyArg_ParseTuple(args, "O!:update_group_mapping_entry", &PyGroupmap, &py_group_map)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       group_map = pytalloc_get_ptr(py_group_map);
+
+       status = methods->update_group_mapping_entry(methods, group_map);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to update group mapping entry, (%d,%s)",
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       talloc_free(tframe);
+       Py_RETURN_NONE;
+}
+
+
+static PyObject *py_pdb_delete_group_mapping_entry(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       TALLOC_CTX *tframe;
+       PyObject *py_group_sid;
+       struct dom_sid *group_sid;
+
+       if (!PyArg_ParseTuple(args, "O!:delete_group_mapping_entry", dom_sid_Type, &py_group_sid)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       group_sid = pytalloc_get_ptr(py_group_sid);
+
+       status = methods->delete_group_mapping_entry(methods, *group_sid);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to delete group mapping entry, (%d,%s)",
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       talloc_free(tframe);
+       Py_RETURN_NONE;
+}
+
+
+static PyObject *py_pdb_enum_group_mapping(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       TALLOC_CTX *tframe;
+       enum lsa_SidType sid_name_use;
+       int lsa_sidtype_value;
+       int unix_only;
+       PyObject *py_domain_sid;
+       struct dom_sid *domain_sid;
+       GROUP_MAP *gmap, *group_map;
+       size_t num_entries;
+       PyObject *py_gmap_list, *py_group_map;
+       int i;
+
+       if (!PyArg_ParseTuple(args, "O!ii:enum_group_mapping", dom_sid_Type, &py_domain_sid,
+                                       &lsa_sidtype_value, &unix_only)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       sid_name_use = lsa_sidtype_value;
+
+       domain_sid = pytalloc_get_ptr(py_domain_sid);
+
+       status = methods->enum_group_mapping(methods, domain_sid, sid_name_use,
+                                               &gmap, &num_entries, unix_only);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to enumerate group mappings, (%d,%s)",
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       py_gmap_list = PyList_New(0);
+       if (py_gmap_list == NULL) {
+               PyErr_NoMemory();
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       for(i=0; i<num_entries; i++) {
+               py_group_map = py_groupmap_new(&PyGroupmap, NULL, NULL);
+               if (py_group_map) {
+                       group_map = pytalloc_get_ptr(py_group_map);
+                       *group_map = gmap[i];
+
+                       PyList_Append(py_gmap_list, py_group_map);
+               }
+       }
+
+       free(gmap);
+       talloc_free(tframe);
+
+       return py_gmap_list;
+}
+
+
+static PyObject *py_pdb_enum_group_members(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       TALLOC_CTX *tframe;
+       PyObject *py_group_sid;
+       struct dom_sid *group_sid;
+       uint32_t *member_rids;
+       size_t num_members;
+       PyObject *py_rid_list;
+       int i;
+
+       if (!PyArg_ParseTuple(args, "O!:enum_group_members", dom_sid_Type, &py_group_sid)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       group_sid = pytalloc_get_ptr(py_group_sid);
+
+       status = methods->enum_group_members(methods, tframe, group_sid,
+                                               &member_rids, &num_members);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to enumerate group members, (%d,%s)",
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       py_rid_list = PyList_New(0);
+       if (py_rid_list == NULL) {
+               PyErr_NoMemory();
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       for(i=0; i<num_members; i++) {
+               PyList_Append(py_rid_list, PyInt_FromLong(member_rids[i]));
+       }
+
+       talloc_free(tframe);
+
+       return py_rid_list;
+}
+
+
+static PyObject *py_pdb_add_groupmem(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       TALLOC_CTX *tframe;
+       uint32_t group_rid, member_rid;
+
+       if (!PyArg_ParseTuple(args, "II:add_groupmem", &group_rid, &member_rid)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       status = methods->add_groupmem(methods, tframe, group_rid, member_rid);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to add group member, (%d,%s)",
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       talloc_free(tframe);
+       Py_RETURN_NONE;
+}
+
+
+static PyObject *py_pdb_del_groupmem(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       TALLOC_CTX *tframe;
+       uint32_t group_rid, member_rid;
+
+       if (!PyArg_ParseTuple(args, "II:del_groupmem", &group_rid, &member_rid)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       status = methods->del_groupmem(methods, tframe, group_rid, member_rid);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to rename sam account, (%d,%s)",
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       talloc_free(tframe);
+       Py_RETURN_NONE;
+}
+
+
+static PyObject *py_pdb_create_alias(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       TALLOC_CTX *tframe;
+       const char *alias_name;
+       uint32_t rid;
+
+       if (!PyArg_ParseTuple(args, "s:create_alias", &alias_name)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       status = methods->create_alias(methods, alias_name, &rid);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to create alias (%s), (%d,%s)",
+                               alias_name,
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       talloc_free(tframe);
+
+       return PyInt_FromLong(rid);
+}
+
+
+static PyObject *py_pdb_delete_alias(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       TALLOC_CTX *tframe;
+       PyObject *py_alias_sid;
+       struct dom_sid *alias_sid;
+
+       if (!PyArg_ParseTuple(args, "O!:delete_alias", dom_sid_Type, &py_alias_sid)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       alias_sid = pytalloc_get_ptr(py_alias_sid);
+
+       status = methods->delete_alias(methods, alias_sid);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to delete alias, (%d,%s)",
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       talloc_free(tframe);
+       Py_RETURN_NONE;
+}
+
+
+static PyObject *py_pdb_get_aliasinfo(pytalloc_Object *self, PyObject *args)
+{
+       NTSTATUS status;
+       struct pdb_methods *methods;
+       TALLOC_CTX *tframe;
+       PyObject *py_alias_sid;
+       struct dom_sid *alias_sid;
+       struct acct_info alias_info;
+       PyObject *py_alias_info;
+
+       if (!PyArg_ParseTuple(args, "O!:get_aliasinfo", dom_sid_Type, &py_alias_sid)) {
+               return NULL;
+       }
+
+       methods = pytalloc_get_ptr(self);
+
+       if ((tframe = talloc_stackframe()) == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       alias_sid = pytalloc_get_ptr(py_alias_sid);
 
-       sid = dom_sid_dup(tframe, &domain_info->sid);
-       if (sid == NULL) {
-               PyErr_NoMemory();
+       status = methods->get_aliasinfo(methods, alias_sid, &alias_info);
+       if (!NT_STATUS_IS_OK(status)) {
+               PyErr_Format(py_pdb_error, "Unable to get alias information, (%d,%s)",
+                               NT_STATUS_V(status),
+                               get_friendly_nt_error_msg(status));
                talloc_free(tframe);
                return NULL;
        }
 
-       guid = talloc(tframe, struct GUID);
-       if (guid == NULL) {
+       py_alias_info = PyDict_New();
+       if (py_alias_info == NULL) {
                PyErr_NoMemory();
                talloc_free(tframe);
                return NULL;
        }
-       *guid = domain_info->guid;
-
-       if ((py_domain_info = PyDict_New()) == NULL) {
-               PyErr_NoMemory();
-               return NULL;
-       }
 
-       PyDict_SetItemString(py_domain_info, "name", PyString_FromString(domain_info->name));
-       PyDict_SetItemString(py_domain_info, "dns_domain", PyString_FromString(domain_info->name));
-       PyDict_SetItemString(py_domain_info, "dns_forest", PyString_FromString(domain_info->name));
-       PyDict_SetItemString(py_domain_info, "dom_sid", pytalloc_steal(dom_sid_Type, sid));
-       PyDict_SetItemString(py_domain_info, "guid", pytalloc_steal(guid_Type, guid));
+       PyDict_SetItemString(py_alias_info, "acct_name", PyString_FromString(alias_info.acct_name));
+       PyDict_SetItemString(py_alias_info, "acct_desc", PyString_FromString(alias_info.acct_desc));
+       PyDict_SetItemString(py_alias_info, "rid", PyInt_FromLong(alias_info.rid));
 
        talloc_free(tframe);
 
-       return py_domain_info;
+       return py_alias_info;
 }
 
 
-static PyObject *py_pdb_getsampwnam(pytalloc_Object *self, PyObject *args)
+static PyObject *py_pdb_set_aliasinfo(pytalloc_Object *self, PyObject *args)
 {
        NTSTATUS status;
-       const char *username;
        struct pdb_methods *methods;
-       struct samu *sam_acct;
-       PyObject *py_sam_acct;
        TALLOC_CTX *tframe;
+       PyObject *py_alias_sid, *py_alias_info;
+       struct dom_sid *alias_sid;
+       struct acct_info alias_info;
 
-       if (!PyArg_ParseTuple(args, "s:getsampwnam", &username)) {
+       if (!PyArg_ParseTuple(args, "O!O:set_alias_info", dom_sid_Type, &py_alias_sid,
+                               &py_alias_info)) {
                return NULL;
        }
 
@@ -1032,39 +2105,35 @@ static PyObject *py_pdb_getsampwnam(pytalloc_Object *self, PyObject *args)
                return NULL;
        }
 
-       py_sam_acct = py_samu_new(&PySamu, NULL, NULL);
-       if (py_sam_acct == NULL) {
-               PyErr_NoMemory();
-               talloc_free(tframe);
-               return NULL;
-       }
-       sam_acct = (struct samu *)pytalloc_get_ptr(py_sam_acct);
+       alias_sid = pytalloc_get_ptr(py_alias_sid);
 
-       status = methods->getsampwnam(methods, sam_acct, username);
+       fstrcpy(alias_info.acct_name, PyString_AsString(PyDict_GetItemString(py_alias_info, "acct_name")));
+       fstrcpy(alias_info.acct_desc, PyString_AsString(PyDict_GetItemString(py_alias_info, "acct_desc")));
+
+       status = methods->set_aliasinfo(methods, alias_sid, &alias_info);
        if (!NT_STATUS_IS_OK(status)) {
-               PyErr_Format(py_pdb_error, "Unable to get user information for '%s', (%d,%s)",
-                               username,
+               PyErr_Format(py_pdb_error, "Unable to set alias information, (%d,%s)",
                                NT_STATUS_V(status),
                                get_friendly_nt_error_msg(status));
-               Py_DECREF(py_sam_acct);
                talloc_free(tframe);
                return NULL;
        }
 
        talloc_free(tframe);
-       return py_sam_acct;
+       Py_RETURN_NONE;
 }
 
-static PyObject *py_pdb_getsampwsid(pytalloc_Object *self, PyObject *args)
+
+static PyObject *py_pdb_add_aliasmem(pytalloc_Object *self, PyObject *args)
 {
        NTSTATUS status;
        struct pdb_methods *methods;
-       struct samu *sam_acct;
-       PyObject *py_sam_acct;
        TALLOC_CTX *tframe;
-       PyObject *py_user_sid;
+       PyObject *py_alias_sid, *py_member_sid;
+       struct dom_sid *alias_sid, *member_sid;
 
-       if (!PyArg_ParseTuple(args, "O:getsampwsid", &py_user_sid)) {
+       if (!PyArg_ParseTuple(args, "O!O!:add_aliasmem", dom_sid_Type, &py_alias_sid,
+                                       dom_sid_Type, &py_member_sid)) {
                return NULL;
        }
 
@@ -1075,38 +2144,33 @@ static PyObject *py_pdb_getsampwsid(pytalloc_Object *self, PyObject *args)
                return NULL;
        }
 
-       py_sam_acct = py_samu_new(&PySamu, NULL, NULL);
-       if (py_sam_acct == NULL) {
-               PyErr_NoMemory();
-               talloc_free(tframe);
-               return NULL;
-       }
-       sam_acct = (struct samu *)pytalloc_get_ptr(py_sam_acct);
+       alias_sid = pytalloc_get_ptr(py_alias_sid);
+       member_sid = pytalloc_get_ptr(py_member_sid);
 
-       status = methods->getsampwsid(methods, sam_acct, pytalloc_get_ptr(py_user_sid));
+       status = methods->add_aliasmem(methods, alias_sid, member_sid);
        if (!NT_STATUS_IS_OK(status)) {
-               PyErr_Format(py_pdb_error, "Unable to get user information from SID, (%d,%s)",
+               PyErr_Format(py_pdb_error, "Unable to add member to alias, (%d,%s)",
                                NT_STATUS_V(status),
                                get_friendly_nt_error_msg(status));
-               Py_DECREF(py_sam_acct);
                talloc_free(tframe);
                return NULL;
        }
 
        talloc_free(tframe);
-       return py_sam_acct;
+       Py_RETURN_NONE;
 }
 
-static PyObject *py_pdb_create_user(pytalloc_Object *self, PyObject *args)
+
+static PyObject *py_pdb_del_aliasmem(pytalloc_Object *self, PyObject *args)
 {
        NTSTATUS status;
        struct pdb_methods *methods;
-       const char *username;
-       unsigned int acct_flags;
-       unsigned int rid;
        TALLOC_CTX *tframe;
+       PyObject *py_alias_sid, *py_member_sid;
+       const struct dom_sid *alias_sid, *member_sid;
 
-       if (!PyArg_ParseTuple(args, "sI:create_user", &username, &acct_flags)) {
+       if (!PyArg_ParseTuple(args, "O!O!:del_aliasmem", dom_sid_Type, &py_alias_sid,
+                                       dom_sid_Type, &py_member_sid)) {
                return NULL;
        }
 
@@ -1117,10 +2181,12 @@ static PyObject *py_pdb_create_user(pytalloc_Object *self, PyObject *args)
                return NULL;
        }
 
-       status = methods->create_user(methods, tframe, username, acct_flags, &rid);
+       alias_sid = pytalloc_get_ptr(py_alias_sid);
+       member_sid = pytalloc_get_ptr(py_member_sid);
+
+       status = methods->del_aliasmem(methods, alias_sid, member_sid);
        if (!NT_STATUS_IS_OK(status)) {
-               PyErr_Format(py_pdb_error, "Unable to create user (%s), (%d,%s)",
-                               username,
+               PyErr_Format(py_pdb_error, "Unable to delete member from alias, (%d,%s)",
                                NT_STATUS_V(status),
                                get_friendly_nt_error_msg(status));
                talloc_free(tframe);
@@ -1128,18 +2194,22 @@ static PyObject *py_pdb_create_user(pytalloc_Object *self, PyObject *args)
        }
 
        talloc_free(tframe);
-       return PyInt_FromLong(rid);
+       Py_RETURN_NONE;
 }
 
-static PyObject *py_pdb_delete_user(pytalloc_Object *self, PyObject *args)
+
+static PyObject *py_pdb_enum_aliasmem(pytalloc_Object *self, PyObject *args)
 {
        NTSTATUS status;
        struct pdb_methods *methods;
        TALLOC_CTX *tframe;
-       struct samu *sam_acct;
-       PyObject *py_sam_acct;
+       PyObject *py_alias_sid;
+       struct dom_sid *alias_sid, *member_sid;
+       PyObject *py_member_list, *py_member_sid;
+       size_t num_members;
+       int i;
 
-       if (!PyArg_ParseTuple(args, "O!:delete_user", &PySamu, &py_sam_acct)) {
+       if (!PyArg_ParseTuple(args, "O!:enum_aliasmem", dom_sid_Type, &py_alias_sid)) {
                return NULL;
        }
 
@@ -1150,32 +2220,47 @@ static PyObject *py_pdb_delete_user(pytalloc_Object *self, PyObject *args)
                return NULL;
        }
 
-       sam_acct = pytalloc_get_ptr(py_sam_acct);
+       alias_sid = pytalloc_get_ptr(py_alias_sid);
 
-       status = methods->delete_user(methods, tframe, sam_acct);
+       status = methods->enum_aliasmem(methods, alias_sid, tframe, &member_sid, &num_members);
        if (!NT_STATUS_IS_OK(status)) {
-               PyErr_Format(py_pdb_error, "Unable to delete user, (%d,%s)",
+               PyErr_Format(py_pdb_error, "Unable to enumerate members for alias, (%d,%s)",
                                NT_STATUS_V(status),
                                get_friendly_nt_error_msg(status));
                talloc_free(tframe);
                return NULL;
        }
 
+       py_member_list = PyList_New(0);
+       if (py_member_list == NULL) {
+               PyErr_NoMemory();
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       for(i=0; i<num_members; i++) {
+               py_member_sid = pytalloc_steal(dom_sid_Type, &member_sid[i]);
+               if (py_member_sid) {
+                       PyList_Append(py_member_list, py_member_sid);
+               }
+       }
+
        talloc_free(tframe);
-       Py_RETURN_NONE;
+
+       return py_member_list;
 }
 
-static PyObject *py_pdb_add_sam_account(pytalloc_Object *self, PyObject *args)
+
+static PyObject *py_pdb_get_account_policy(pytalloc_Object *self)
 {
        NTSTATUS status;
        struct pdb_methods *methods;
        TALLOC_CTX *tframe;
-       struct samu *sam_acct;
-       PyObject *py_sam_acct;
-
-       if (!PyArg_ParseTuple(args, "O!:add_sam_account", &PySamu, &py_sam_acct)) {
-               return NULL;
-       }
+       PyObject *py_acct_policy;
+       uint32_t value;
+       const char **names;
+       int count, i;
+       enum pdb_policy_type type;
 
        methods = pytalloc_get_ptr(self);
 
@@ -1184,30 +2269,38 @@ static PyObject *py_pdb_add_sam_account(pytalloc_Object *self, PyObject *args)
                return NULL;
        }
 
-       sam_acct = pytalloc_get_ptr(py_sam_acct);
-
-       status = methods->add_sam_account(methods, sam_acct);
-       if (!NT_STATUS_IS_OK(status)) {
-               PyErr_Format(py_pdb_error, "Unable to add sam account, (%d,%s)",
-                               NT_STATUS_V(status),
-                               get_friendly_nt_error_msg(status));
-               talloc_free(tframe);
+       py_acct_policy = PyDict_New();
+       if (py_acct_policy == NULL) {
+               PyErr_NoMemory();
                return NULL;
        }
 
+       account_policy_names_list(tframe, &names, &count);
+       for (i=0; i<count; i++) {
+               type = account_policy_name_to_typenum(names[i]);
+               status = methods->get_account_policy(methods, type, &value);
+               if (NT_STATUS_IS_OK(status)) {
+                       PyDict_SetItemString(py_acct_policy, names[i], PyInt_FromLong(value));
+               }
+       }
+
        talloc_free(tframe);
-       Py_RETURN_NONE;
+
+       return py_acct_policy;
 }
 
-static PyObject *py_pdb_update_sam_account(pytalloc_Object *self, PyObject *args)
+
+static PyObject *py_pdb_set_account_policy(pytalloc_Object *self, PyObject *args)
 {
        NTSTATUS status;
        struct pdb_methods *methods;
        TALLOC_CTX *tframe;
-       struct samu *sam_acct;
-       PyObject *py_sam_acct;
+       PyObject *py_acct_policy, *py_value;
+       const char **names;
+       int count, i;
+       enum pdb_policy_type type;
 
-       if (!PyArg_ParseTuple(args, "O!:update_sam_account", &PySamu, &py_sam_acct)) {
+       if (!PyArg_ParseTuple(args, "O!:set_account_policy", PyDict_Type, &py_acct_policy)) {
                return NULL;
        }
 
@@ -1218,30 +2311,37 @@ static PyObject *py_pdb_update_sam_account(pytalloc_Object *self, PyObject *args
                return NULL;
        }
 
-       sam_acct = pytalloc_get_ptr(py_sam_acct);
-
-       status = methods->update_sam_account(methods, sam_acct);
-       if (!NT_STATUS_IS_OK(status)) {
-               PyErr_Format(py_pdb_error, "Unable to update sam account, (%d,%s)",
-                               NT_STATUS_V(status),
-                               get_friendly_nt_error_msg(status));
-               talloc_free(tframe);
-               return NULL;
+       account_policy_names_list(tframe, &names, &count);
+       for (i=0; i<count; i++) {
+               if ((py_value = PyDict_GetItemString(py_acct_policy, names[i])) != NULL) {
+                       type = account_policy_name_to_typenum(names[i]);
+                       status = methods->set_account_policy(methods, type, PyInt_AsLong(py_value));
+                       if (!NT_STATUS_IS_OK(status)) {
+                               PyErr_Format(py_pdb_error, "Error setting account policy (%s), (%d,%s)",
+                                               names[i],
+                                               NT_STATUS_V(status),
+                                               get_friendly_nt_error_msg(status));
+                       }
+               }
        }
 
+
        talloc_free(tframe);
+
        Py_RETURN_NONE;
 }
 
-static PyObject *py_pdb_delete_sam_account(pytalloc_Object *self, PyObject *args)
+static PyObject *py_pdb_search_users(pytalloc_Object *self, PyObject *args)
 {
        NTSTATUS status;
        struct pdb_methods *methods;
        TALLOC_CTX *tframe;
-       struct samu *sam_acct;
-       PyObject *py_sam_acct;
+       unsigned int acct_flags;
+       struct pdb_search *search;
+       struct samr_displayentry *entry;
+       PyObject *py_userlist, *py_dict;
 
-       if (!PyArg_ParseTuple(args, "O!:delete_sam_account", &PySamu, &py_sam_acct)) {
+       if (!PyArg_ParseTuple(args, "I:search_users", &acct_flags)) {
                return NULL;
        }
 
@@ -1252,34 +2352,65 @@ static PyObject *py_pdb_delete_sam_account(pytalloc_Object *self, PyObject *args
                return NULL;
        }
 
-       sam_acct = pytalloc_get_ptr(py_sam_acct);
+       search = talloc_zero(tframe, struct pdb_search);
+       if (search == NULL) {
+               PyErr_NoMemory();
+               talloc_free(tframe);
+               return NULL;
+       }
 
-       status = methods->delete_sam_account(methods, sam_acct);
-       if (!NT_STATUS_IS_OK(status)) {
-               PyErr_Format(py_pdb_error, "Unable to delete sam account, (%d,%s)",
+       if (!methods->search_users(methods, search, acct_flags)) {
+               PyErr_Format(py_pdb_error, "Unable to search users, (%d,%s)",
                                NT_STATUS_V(status),
                                get_friendly_nt_error_msg(status));
                talloc_free(tframe);
                return NULL;
        }
 
+       entry = talloc_zero(tframe, struct samr_displayentry);
+       if (entry == NULL) {
+               PyErr_NoMemory();
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       py_userlist = PyList_New(0);
+       if (py_userlist == NULL) {
+               PyErr_NoMemory();
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       while (search->next_entry(search, entry)) {
+               py_dict = PyDict_New();
+               if (py_dict == NULL) {
+                       PyErr_NoMemory();
+               } else {
+                       PyDict_SetItemString(py_dict, "idx", PyInt_FromLong(entry->idx));
+                       PyDict_SetItemString(py_dict, "rid", PyInt_FromLong(entry->rid));
+                       PyDict_SetItemString(py_dict, "acct_flags", PyInt_FromLong(entry->acct_flags));
+                       PyDict_SetItemString(py_dict, "account_name", PyString_FromString(entry->account_name));
+                       PyDict_SetItemString(py_dict, "fullname", PyString_FromString(entry->fullname));
+                       PyDict_SetItemString(py_dict, "description", PyString_FromString(entry->description));
+                       PyList_Append(py_userlist, py_dict);
+               }
+       }
+       search->search_end(search);
+
        talloc_free(tframe);
-       Py_RETURN_NONE;
+
+       return py_userlist;
 }
 
-static PyObject *py_pdb_rename_sam_account(pytalloc_Object *self, PyObject *args)
+
+static PyObject *py_pdb_search_groups(pytalloc_Object *self)
 {
        NTSTATUS status;
        struct pdb_methods *methods;
        TALLOC_CTX *tframe;
-       struct samu *sam_acct;
-       const char *new_username;
-       PyObject *py_sam_acct;
-
-       if (!PyArg_ParseTuple(args, "O!s:rename_sam_account", &PySamu, &py_sam_acct,
-                                       &new_username)) {
-               return NULL;
-       }
+       struct pdb_search *search;
+       struct samr_displayentry *entry;
+       PyObject *py_grouplist, *py_dict;
 
        methods = pytalloc_get_ptr(self);
 
@@ -1288,32 +2419,69 @@ static PyObject *py_pdb_rename_sam_account(pytalloc_Object *self, PyObject *args
                return NULL;
        }
 
-       sam_acct = pytalloc_get_ptr(py_sam_acct);
+       search = talloc_zero(tframe, struct pdb_search);
+       if (search == NULL) {
+               PyErr_NoMemory();
+               talloc_free(tframe);
+               return NULL;
+       }
 
-       status = methods->rename_sam_account(methods, sam_acct, new_username);
-       if (!NT_STATUS_IS_OK(status)) {
-               PyErr_Format(py_pdb_error, "Unable to rename sam account, (%d,%s)",
+       if (!methods->search_groups(methods, search)) {
+               PyErr_Format(py_pdb_error, "Unable to search groups, (%d,%s)",
                                NT_STATUS_V(status),
                                get_friendly_nt_error_msg(status));
                talloc_free(tframe);
                return NULL;
        }
 
+       entry = talloc_zero(tframe, struct samr_displayentry);
+       if (entry == NULL) {
+               PyErr_NoMemory();
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       py_grouplist = PyList_New(0);
+       if (py_grouplist == NULL) {
+               PyErr_NoMemory();
+               talloc_free(tframe);
+               return NULL;
+       }
+
+       while (search->next_entry(search, entry)) {
+               py_dict = PyDict_New();
+               if (py_dict == NULL) {
+                       PyErr_NoMemory();
+               } else {
+                       PyDict_SetItemString(py_dict, "idx", PyInt_FromLong(entry->idx));
+                       PyDict_SetItemString(py_dict, "rid", PyInt_FromLong(entry->rid));
+                       PyDict_SetItemString(py_dict, "acct_flags", PyInt_FromLong(entry->acct_flags));
+                       PyDict_SetItemString(py_dict, "account_name", PyString_FromString(entry->account_name));
+                       PyDict_SetItemString(py_dict, "fullname", PyString_FromString(entry->fullname));
+                       PyDict_SetItemString(py_dict, "description", PyString_FromString(entry->description));
+                       PyList_Append(py_grouplist, py_dict);
+               }
+       }
+       search->search_end(search);
+
        talloc_free(tframe);
-       Py_RETURN_NONE;
+
+       return py_grouplist;
 }
 
-static PyObject *py_pdb_search_users(pytalloc_Object *self, PyObject *args)
+
+static PyObject *py_pdb_search_aliases(pytalloc_Object *self, PyObject *args)
 {
        NTSTATUS status;
        struct pdb_methods *methods;
        TALLOC_CTX *tframe;
-       unsigned int acct_flags;
        struct pdb_search *search;
        struct samr_displayentry *entry;
-       PyObject *py_userlist, *py_dict;
+       PyObject *py_aliaslist, *py_dict;
+       PyObject *py_domain_sid;
+       struct dom_sid *dom_sid;
 
-       if (!PyArg_ParseTuple(args, "I:search_users", &acct_flags)) {
+       if (!PyArg_ParseTuple(args, "O!:search_users", dom_sid_Type, &py_domain_sid)) {
                return NULL;
        }
 
@@ -1324,6 +2492,8 @@ static PyObject *py_pdb_search_users(pytalloc_Object *self, PyObject *args)
                return NULL;
        }
 
+       dom_sid = pytalloc_get_ptr(py_domain_sid);
+
        search = talloc_zero(tframe, struct pdb_search);
        if (search == NULL) {
                PyErr_NoMemory();
@@ -1331,8 +2501,8 @@ static PyObject *py_pdb_search_users(pytalloc_Object *self, PyObject *args)
                return NULL;
        }
 
-       if (!methods->search_users(methods, search, acct_flags)) {
-               PyErr_Format(py_pdb_error, "Unable to search users, (%d,%s)",
+       if (!methods->search_aliases(methods, search, dom_sid)) {
+               PyErr_Format(py_pdb_error, "Unable to search aliases, (%d,%s)",
                                NT_STATUS_V(status),
                                get_friendly_nt_error_msg(status));
                talloc_free(tframe);
@@ -1346,8 +2516,8 @@ static PyObject *py_pdb_search_users(pytalloc_Object *self, PyObject *args)
                return NULL;
        }
 
-       py_userlist = PyList_New(0);
-       if (py_userlist == NULL) {
+       py_aliaslist = PyList_New(0);
+       if (py_aliaslist == NULL) {
                PyErr_NoMemory();
                talloc_free(tframe);
                return NULL;
@@ -1364,26 +2534,26 @@ static PyObject *py_pdb_search_users(pytalloc_Object *self, PyObject *args)
                        PyDict_SetItemString(py_dict, "account_name", PyString_FromString(entry->account_name));
                        PyDict_SetItemString(py_dict, "fullname", PyString_FromString(entry->fullname));
                        PyDict_SetItemString(py_dict, "description", PyString_FromString(entry->description));
-                       PyList_Append(py_userlist, py_dict);
+                       PyList_Append(py_aliaslist, py_dict);
                }
        }
        search->search_end(search);
 
        talloc_free(tframe);
 
-       return py_userlist;
+       return py_aliaslist;
 }
 
 static PyMethodDef py_pdb_methods[] = {
        { "domain_info", (PyCFunction)py_pdb_domain_info, METH_NOARGS,
                "domain_info() -> str\n\n \
-               Get domain for the database." },
+               Get domain information for the database." },
        { "getsampwnam", (PyCFunction)py_pdb_getsampwnam, METH_VARARGS,
                "getsampwnam(username) -> samu object\n\n \
-               Get user information." },
+               Get user information by name." },
        { "getsampwsid", (PyCFunction)py_pdb_getsampwsid, METH_VARARGS,
-               "getsampwsid(sid) -> samu object\n\n \
-               Get user information from user_sid (dcerpc.security.dom_sid object)." },
+               "getsampwsid(user_sid) -> samu object\n\n \
+               Get user information by sid (dcerpc.security.dom_sid object)." },
        { "create_user", (PyCFunction)py_pdb_create_user, METH_VARARGS,
                "create_user(username, acct_flags) -> rid\n\n \
                Create user. acct_flags are samr account control flags." },
@@ -1402,11 +2572,105 @@ static PyMethodDef py_pdb_methods[] = {
        { "rename_sam_account", (PyCFunction)py_pdb_rename_sam_account, METH_VARARGS,
                "rename_sam_account(samu object1, new_username) -> None\n\n \
                Rename SAM account." },
+       /* update_login_attempts */
+       { "getgrsid", (PyCFunction)py_pdb_getgrsid, METH_VARARGS,
+               "getgrsid(group_sid) -> groupmap object\n\n \
+               Get group information by sid (dcerpc.security.dom_sid object)." },
+       { "getgrgid", (PyCFunction)py_pdb_getgrgid, METH_VARARGS,
+               "getgrsid(gid) -> groupmap object\n\n \
+               Get group information by gid." },
+       { "getgrnam", (PyCFunction)py_pdb_getgrnam, METH_VARARGS,
+               "getgrsid(groupname) -> groupmap object\n\n \
+               Get group information by name." },
+       { "create_dom_group", (PyCFunction)py_pdb_create_dom_group, METH_VARARGS,
+               "create_dom_group(groupname) -> group_rid\n\n \
+               Create new domain group by name." },
+       { "delete_dom_group", (PyCFunction)py_pdb_delete_dom_group, METH_VARARGS,
+               "delete_dom_group(group_rid) -> None\n\n \
+               Delete domain group identified by rid" },
+       { "add_group_mapping_entry", (PyCFunction)py_pdb_add_group_mapping_entry, METH_VARARGS,
+               "add_group_mapping_entry(groupmap) -> None\n \
+               Add group mapping entry for groupmap object." },
+       { "update_group_mapping_entry", (PyCFunction)py_pdb_update_group_mapping_entry, METH_VARARGS,
+               "update_group_mapping_entry(groupmap) -> None\n\n \
+               Update group mapping entry for groupmap object." },
+       { "delete_group_mapping_entry", (PyCFunction)py_pdb_delete_group_mapping_entry, METH_VARARGS,
+               "delete_group_mapping_entry(groupmap) -> None\n\n \
+               Delete group mapping entry for groupmap object." },
+       { "enum_group_mapping", (PyCFunction)py_pdb_enum_group_mapping, METH_VARARGS,
+               "enum_group_mapping(domain_sid) -> List\n\n \
+               Return list of group mappings as groupmap objects." },
+       { "enum_group_members", (PyCFunction)py_pdb_enum_group_members, METH_VARARGS,
+               "enum_group_members(group_sid) -> List\n\n \
+               Return list of group members." },
+       /* enum_group_memberships */
+       /* set_unix_primary_group */
+       { "add_groupmem", (PyCFunction)py_pdb_add_groupmem, METH_VARARGS,
+               "add_groupmem(group_rid, member_rid) -> None\n\n \
+               Add user to group." },
+       { "del_groupmem", (PyCFunction)py_pdb_del_groupmem, METH_VARARGS,
+               "del_groupmem(group_rid, member_rid) -> None\n\n \
+               Remove user from from group." },
+       { "create_alias", (PyCFunction)py_pdb_create_alias, METH_VARARGS,
+               "create_alias(alias_name) -> alias_rid\n\n \
+               Create alias entry." },
+       { "delete_alias", (PyCFunction)py_pdb_delete_alias, METH_VARARGS,
+               "delete_alias(alias_sid) -> None\n\n \
+               Delete alias entry." },
+       { "get_aliasinfo", (PyCFunction)py_pdb_get_aliasinfo, METH_VARARGS,
+               "get_aliasinfo(alias_sid) -> Mapping\n\n \
+               Get alias information as a dictionary with keys - acct_name, acct_desc, rid." },
+       { "set_aliasinfo", (PyCFunction)py_pdb_set_aliasinfo, METH_VARARGS,
+               "set_alias_info(alias_sid, Mapping) -> None\n\n \
+               Set alias information from a dictionary with keys - acct_name, acct_desc." },
+       { "add_aliasmem", (PyCFunction)py_pdb_add_aliasmem, METH_VARARGS,
+               "add_aliasmem(alias_sid, member_sid) -> None\n\n \
+               Add user to alias entry." },
+       { "del_aliasmem", (PyCFunction)py_pdb_del_aliasmem, METH_VARARGS,
+               "del_aliasmem(alias_sid, member_sid) -> None\n\n \
+               Remove a user from alias entry." },
+       { "enum_aliasmem", (PyCFunction)py_pdb_enum_aliasmem, METH_VARARGS,
+               "enum_aliasmem(alias_sid) -> List\n\n \
+               Return a list of users for alias entry." },
+       /* enum_alias_memberships */
+       /* lookup_rids */
+       /* lookup_names */
+       { "get_account_policy", (PyCFunction)py_pdb_get_account_policy, METH_NOARGS,
+               "get_account_policy() -> Mapping\n\n \
+               Get account policy information as a dictionary." },
+       { "set_account_policy", (PyCFunction)py_pdb_set_account_policy, METH_VARARGS,
+               "get_account_policy(Mapping) -> None\n\n \
+               Set account policy settings from a dicionary." },
+       /* get_seq_num */
        { "search_users", (PyCFunction)py_pdb_search_users, METH_VARARGS,
                "search_users(acct_flags) -> List\n\n \
                Search users. acct_flags are samr account control flags.\n \
-               Each entry in the list is a dictionary with keys - \
-               idx, rid, acct_flags, account_name, fullname, description." },
+               Each list entry is dictionary with keys - idx, rid, acct_flags, account_name, fullname, description." },
+       { "search_groups", (PyCFunction)py_pdb_search_groups, METH_NOARGS,
+               "search_groups() -> List\n\n \
+               Search unix only groups. \n \
+               Each list entry is dictionary with keys - idx, rid, acct_flags, account_name, fullname, description." },
+       { "search_aliases", (PyCFunction)py_pdb_search_aliases, METH_VARARGS,
+               "search_aliases(domain_sid) -> List\n\n \
+               Search aliases. domain_sid is dcerpc.security.dom_sid object.\n \
+               Each list entry is dictionary with keys - idx, rid, acct_flags, account_name, fullname, description." },
+       /* uid_to_sid */
+       /* gid_to_sid */
+       /* sid_to_id */
+       /* capabilities */
+       /* new_rid */
+       /* get_trusteddom_pw */
+       /* set_trusteddom_pw */
+       /* del_trusteddom_pw */
+       /* enum_trusteddoms */
+       /* get_trusted_domain */
+       /* get_trusted_domain_by_sid */
+       /* set_trusted_domain */
+       /* del_trusted_domain */
+       /* enum_trusted_domains */
+       /* get_secret */
+       /* set_secret */
+       /* delete_secret */
        { NULL },
 };
 
@@ -1603,6 +2867,11 @@ void initpassdb(void)
                return;
        }
 
+       PyGroupmap.tp_base = talloc_type;
+       if (PyType_Ready(&PyGroupmap) < 0) {
+               return;
+       }
+
        m = Py_InitModule3("passdb", py_passdb_methods, "SAMBA Password Database");
        if (m == NULL) {
            return;
@@ -1616,6 +2885,12 @@ void initpassdb(void)
        Py_INCREF(&PyPDB);
        PyModule_AddObject(m, "PDB", (PyObject *)&PyPDB);
 
+       Py_INCREF(&PySamu);
+       PyModule_AddObject(m, "Samu", (PyObject *)&PySamu);
+
+       Py_INCREF(&PyGroupmap);
+       PyModule_AddObject(m, "Groupmap", (PyObject *)&PyGroupmap);
+
        /* Import dom_sid type from dcerpc.security */
        mod = PyImport_ImportModule("samba.dcerpc.security");
        if (mod == NULL) {