pysss.c revision d2d2d6ae0c436461bcc8f881df059eb036314c44
/*
Authors:
Jakub Hrozek <jhrozek@redhat.com>
Copyright (C) 2009 Red Hat
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Python.h>
#include <structmember.h>
#include <talloc.h>
#include <pwd.h>
#include <grp.h>
#include "util/util.h"
#include "util/sss_python.h"
#include "db/sysdb.h"
#include "tools/tools_util.h"
#include "tools/sss_sync_ops.h"
#include "util/crypto/sss_crypto.h"
/*
* function taken from samba sources tree as of Aug 20 2009,
* file source4/lib/ldb/pyldb.c
*/
static char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list,
const char *paramname)
{
char **ret;
int i;
ret = talloc_array(mem_ctx, char *, PyList_Size(list)+1);
for (i = 0; i < PyList_Size(list); i++) {
PyObject *item = PyList_GetItem(list, i);
if (!PyString_Check(item)) {
PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
return NULL;
}
ret[i] = talloc_strndup(ret, PyString_AsString(item),
PyString_Size(item));
}
ret[i] = NULL;
return ret;
}
/* ======================= sysdb python wrappers ==========================*/
/*
* The sss.password object
*/
typedef struct {
PyObject_HEAD
TALLOC_CTX *mem_ctx;
struct tevent_context *ev;
struct sysdb_ctx *sysdb;
struct confdb_ctx *confdb;
struct sss_domain_info *local;
int lock;
int unlock;
} PySssLocalObject;
/*
* The transaction object
*/
struct py_sss_transaction {
PySssLocalObject *self;
struct ops_ctx *ops;
bool transaction_done;
int error;
};
/*
* Error reporting
*/
static void PyErr_SetSssErrorWithMessage(int ret, const char *message)
{
PyObject *exc = Py_BuildValue(discard_const_p(char, "(is)"),
ret, message);
PyErr_SetObject(PyExc_IOError, exc);
Py_XDECREF(exc);
}
static void PyErr_SetSssError(int ret)
{
PyErr_SetSssErrorWithMessage(ret, strerror(ret));
}
/*
* Common init of all methods
*/
static struct tools_ctx *init_ctx(PySssLocalObject *self)
{
struct ops_ctx *octx = NULL;
struct tools_ctx *tctx = NULL;
tctx = talloc_zero(self->mem_ctx, struct tools_ctx);
if (tctx == NULL) {
return NULL;
}
tctx->confdb = self->confdb;
tctx->sysdb = self->sysdb;
tctx->local = self->local;
/* tctx->nctx is NULL here, which is OK since we don't parse domains
* in the python bindings (yet?) */
octx = talloc_zero(tctx, struct ops_ctx);
if (octx == NULL) {
PyErr_NoMemory();
return NULL;
}
octx->domain = self->local;
tctx->octx = octx;
return tctx;
}
/*
* Add a user
*/
PyDoc_STRVAR(py_sss_useradd__doc__,
"Add a user named ``username``.\n\n"
":param username: name of the user\n\n"
":param kwargs: Keyword arguments that customize the operation\n\n"
"* useradd can be customized further with keyword arguments:\n"
" * ``uid``: The UID of the user\n"
" * ``gid``: The GID of the user\n"
" * ``gecos``: The comment string\n"
" * ``homedir``: Home directory\n"
" * ``shell``: Login shell\n"
" * ``skel``: Specify an alternative skeleton directory\n"
" * ``create_home``: (bool) Force creation of home directory on or off\n"
" * ``groups``: List of groups the user is member of\n");
static PyObject *py_sss_useradd(PySssLocalObject *self,
PyObject *args,
PyObject *kwds)
{
struct tools_ctx *tctx = NULL;
unsigned long uid = 0;
unsigned long gid = 0;
const char *gecos = NULL;
const char *home = NULL;
const char *shell = NULL;
const char *skel = NULL;
char *username = NULL;
int ret;
const char * const kwlist[] = { "username", "uid", "gid", "gecos",
"homedir", "shell", "skel",
"create_home", "groups", NULL };
PyObject *py_groups = Py_None;
PyObject *py_create_home = Py_None;
int create_home = 0;
/* parse arguments */
if (!PyArg_ParseTupleAndKeywords(args, kwds,
discard_const_p(char, "s|kkssssO!O!"),
discard_const_p(char *, kwlist),
&username,
&uid,
&gid,
&gecos,
&home,
&shell,
&skel,
&PyBool_Type,
&py_create_home,
&PyList_Type,
&py_groups)) {
goto fail;
}
tctx = init_ctx(self);
if (!tctx) {
PyErr_NoMemory();
return NULL;
}
if (py_groups != Py_None) {
tctx->octx->addgroups = PyList_AsStringList(tctx, py_groups, "groups");
if (!tctx->octx->addgroups) {
PyErr_NoMemory();
return NULL;
}
}
/* user-wise the parameter is only bool - do or don't,
* however we must have a third state - undecided, pick default */
if (py_create_home == Py_True) {
create_home = DO_CREATE_HOME;
} else if (py_create_home == Py_False) {
create_home = DO_NOT_CREATE_HOME;
}
tctx->octx->name = username;
tctx->octx->uid = uid;
/* fill in defaults */
ret = useradd_defaults(tctx,
self->confdb,
tctx->octx, gecos,
home, shell,
create_home,
skel);
if (ret != EOK) {
PyErr_SetSssError(ret);
goto fail;
}
/* Add the user within a transaction */
tctx->error = sysdb_transaction_start(tctx->sysdb);
if (tctx->error != EOK) {
PyErr_SetSssError(tctx->error);
goto fail;
}
/* useradd */
tctx->error = useradd(tctx, tctx->sysdb, tctx->octx);
if (tctx->error) {
/* cancel transaction */
sysdb_transaction_cancel(tctx->sysdb);
PyErr_SetSssError(tctx->error);
goto fail;
}
tctx->error = sysdb_transaction_commit(tctx->sysdb);
if (tctx->error) {
PyErr_SetSssError(tctx->error);
goto fail;
}
/* Create user's home directory and/or mail spool */
if (tctx->octx->create_homedir) {
/* We need to know the UID and GID of the user, if
* sysdb did assign it automatically, do a lookup */
if (tctx->octx->uid == 0 || tctx->octx->gid == 0) {
ret = sysdb_getpwnam_sync(tctx,
tctx->sysdb,
tctx->octx->name,
tctx->octx);
if (ret != EOK) {
PyErr_SetSssError(ret);
goto fail;
}
}
ret = create_homedir(tctx->octx->skeldir,
tctx->octx->home,
tctx->octx->uid,
tctx->octx->gid,
tctx->octx->umask);
if (ret != EOK) {
PyErr_SetSssError(ret);
goto fail;
}
/* failure here should not be fatal */
create_mail_spool(tctx,
tctx->octx->name,
tctx->octx->maildir,
tctx->octx->uid,
tctx->octx->gid);
}
talloc_zfree(tctx);
Py_RETURN_NONE;
fail:
talloc_zfree(tctx);
return NULL;
}
/*
* Delete a user
*/
PyDoc_STRVAR(py_sss_userdel__doc__,
"Remove the user named ``username``.\n\n"
":param username: Name of user being removed\n"
":param kwargs: Keyword arguments that customize the operation\n\n"
"* userdel can be customized further with keyword arguments:\n"
" * ``force``: (bool) Force removal of files not owned by the user\n"
" * ``remove``: (bool) Toggle removing home directory and mail spool\n");
static PyObject *py_sss_userdel(PySssLocalObject *self,
PyObject *args,
PyObject *kwds)
{
struct tools_ctx *tctx = NULL;
char *username = NULL;
int ret;
PyObject *py_remove = Py_None;
int remove_home = 0;
PyObject *py_force = Py_None;
const char * const kwlist[] = { "username", "remove", "force", NULL };
if(!PyArg_ParseTupleAndKeywords(args, kwds,
discard_const_p(char, "s|O!O!"),
discard_const_p(char *, kwlist),
&username,
&PyBool_Type,
&py_remove,
&PyBool_Type,
&py_force)) {
goto fail;
}
tctx = init_ctx(self);
if (!tctx) {
PyErr_NoMemory();
return NULL;
}
tctx->octx->name = username;
if (py_remove == Py_True) {
remove_home = DO_REMOVE_HOME;
} else if (py_remove == Py_False) {
remove_home = DO_NOT_REMOVE_HOME;
}
/*
* Fills in defaults for ops_ctx user did not specify.
*/
ret = userdel_defaults(tctx,
tctx->confdb,
tctx->octx,
remove_home);
if (ret != EOK) {
PyErr_SetSssError(ret);
goto fail;
}
ret = run_userdel_cmd(tctx);
if (ret != EOK) {
PyErr_SetSssError(ret);
goto fail;
}
if (tctx->octx->remove_homedir) {
ret = sysdb_getpwnam_sync(tctx,
tctx->sysdb,
tctx->octx->name,
tctx->octx);
if (ret != EOK) {
PyErr_SetSssError(ret);
goto fail;
}
}
/* Delete the user */
ret = userdel(tctx, self->sysdb, tctx->octx);
if (ret != EOK) {
PyErr_SetSssError(ret);
goto fail;
}
if (tctx->octx->remove_homedir) {
ret = remove_homedir(tctx,
tctx->octx->home,
tctx->octx->maildir,
tctx->octx->name,
tctx->octx->uid,
(py_force == Py_True));
if (ret != EOK) {
PyErr_SetSssError(ret);
goto fail;
}
}
talloc_zfree(tctx);
Py_RETURN_NONE;
fail:
talloc_zfree(tctx);
return NULL;
}
/*
* Modify a user
*/
PyDoc_STRVAR(py_sss_usermod__doc__,
"Modify a user.\n\n"
":param username: Name of user being modified\n\n"
":param kwargs: Keyword arguments that customize the operation\n\n"
"* usermod can be customized further with keyword arguments:\n"
" * ``uid``: The UID of the user\n"
" * ``gid``: The GID of the user\n"
" * ``gecos``: The comment string\n"
" * ``homedir``: Home directory\n"
" * ``shell``: Login shell\n"
" * ``addgroups``: List of groups to add the user to\n"
" * ``rmgroups``: List of groups to remove the user from\n"
" * ``lock``: Lock or unlock the account\n");
static PyObject *py_sss_usermod(PySssLocalObject *self,
PyObject *args,
PyObject *kwds)
{
struct tools_ctx *tctx = NULL;
PyObject *py_addgroups = Py_None;
PyObject *py_rmgroups = Py_None;
unsigned long uid = 0;
unsigned long gid = 0;
char *gecos = NULL;
char *home = NULL;
char *shell = NULL;
char *username = NULL;
unsigned long lock = 0;
const char * const kwlist[] = { "username", "uid", "gid", "lock",
"gecos", "homedir", "shell",
"addgroups", "rmgroups", NULL };
/* parse arguments */
if (!PyArg_ParseTupleAndKeywords(args, kwds,
discard_const_p(char, "s|kkksssO!O!"),
discard_const_p(char *, kwlist),
&username,
&uid,
&gid,
&lock,
&gecos,
&home,
&shell,
&PyList_Type,
&py_addgroups,
&PyList_Type,
&py_rmgroups)) {
goto fail;
}
tctx = init_ctx(self);
if (!tctx) {
PyErr_NoMemory();
return NULL;
}
if (lock && lock != DO_LOCK && lock != DO_UNLOCK) {
PyErr_SetString(PyExc_ValueError,
"Unkown value for lock parameter");
goto fail;
}
if (py_addgroups != Py_None) {
tctx->octx->addgroups = PyList_AsStringList(tctx,
py_addgroups,
"addgroups");
if (!tctx->octx->addgroups) {
return NULL;
}
}
if (py_rmgroups != Py_None) {
tctx->octx->rmgroups = PyList_AsStringList(tctx,
py_rmgroups,
"rmgroups");
if (!tctx->octx->rmgroups) {
return NULL;
}
}
tctx->octx->name = username;
tctx->octx->uid = uid;
tctx->octx->gid = gid;
tctx->octx->gecos = gecos;
tctx->octx->home = home;
tctx->octx->shell = shell;
tctx->octx->lock = lock;
/* Modify the user within a transaction */
tctx->error = sysdb_transaction_start(tctx->sysdb);
if (tctx->error != EOK) {
PyErr_SetSssError(tctx->error);
goto fail;
}
/* usermod */
tctx->error = usermod(tctx, tctx->sysdb, tctx->octx);
if (tctx->error) {
/* cancel transaction */
sysdb_transaction_cancel(tctx->sysdb);
PyErr_SetSssError(tctx->error);
goto fail;
}
tctx->error = sysdb_transaction_commit(tctx->sysdb);
if (tctx->error) {
PyErr_SetSssError(tctx->error);
goto fail;
}
talloc_zfree(tctx);
Py_RETURN_NONE;
fail:
talloc_zfree(tctx);
return NULL;
}
/*
* Add a group
*/
PyDoc_STRVAR(py_sss_groupadd__doc__,
"Add a group.\n\n"
":param groupname: Name of group being added\n\n"
":param kwargs: Keyword arguments ro customize the operation\n\n"
"* groupmod can be customized further with keyword arguments:\n"
" * ``gid``: The GID of the group\n");
static PyObject *py_sss_groupadd(PySssLocalObject *self,
PyObject *args,
PyObject *kwds)
{
struct tools_ctx *tctx = NULL;
char *groupname;
unsigned long gid = 0;
const char * const kwlist[] = { "groupname", "gid", NULL };
/* parse arguments */
if (!PyArg_ParseTupleAndKeywords(args, kwds,
discard_const_p(char, "s|k"),
discard_const_p(char *, kwlist),
&groupname,
&gid)) {
goto fail;
}
tctx = init_ctx(self);
if (!tctx) {
PyErr_NoMemory();
return NULL;
}
tctx->octx->name = groupname;
tctx->octx->gid = gid;
/* Add the group within a transaction */
tctx->error = sysdb_transaction_start(tctx->sysdb);
if (tctx->error != EOK) {
PyErr_SetSssError(tctx->error);
goto fail;
}
/* groupadd */
tctx->error = groupadd(tctx->sysdb, tctx->octx);
if (tctx->error) {
/* cancel transaction */
sysdb_transaction_cancel(tctx->sysdb);
PyErr_SetSssError(tctx->error);
goto fail;
}
tctx->error = sysdb_transaction_commit(tctx->sysdb);
if (tctx->error) {
PyErr_SetSssError(tctx->error);
goto fail;
}
talloc_zfree(tctx);
Py_RETURN_NONE;
fail:
talloc_zfree(tctx);
return NULL;
}
/*
* Delete a group
*/
PyDoc_STRVAR(py_sss_groupdel__doc__,
"Remove a group.\n\n"
":param groupname: Name of group being removed\n");
static PyObject *py_sss_groupdel(PySssLocalObject *self,
PyObject *args,
PyObject *kwds)
{
struct tools_ctx *tctx = NULL;
char *groupname = NULL;
int ret;
if(!PyArg_ParseTuple(args, discard_const_p(char, "s"), &groupname)) {
goto fail;
}
tctx = init_ctx(self);
if (!tctx) {
PyErr_NoMemory();
return NULL;
}
tctx->octx->name = groupname;
/* Remove the group */
ret = groupdel(tctx, self->sysdb, tctx->octx);
if (ret != EOK) {
PyErr_SetSssError(ret);
goto fail;
}
talloc_zfree(tctx);
Py_RETURN_NONE;
fail:
talloc_zfree(tctx);
return NULL;
}
/*
* Modify a group
*/
PyDoc_STRVAR(py_sss_groupmod__doc__,
"Modify a group.\n\n"
":param groupname: Name of group being modified\n\n"
":param kwargs: Keyword arguments ro customize the operation\n\n"
"* groupmod can be customized further with keyword arguments:\n"
" * ``gid``: The GID of the group\n\n"
" * ``addgroups``: Groups to add the group to\n\n"
" * ``rmgroups``: Groups to remove the group from\n\n");
static PyObject *py_sss_groupmod(PySssLocalObject *self,
PyObject *args,
PyObject *kwds)
{
struct tools_ctx *tctx = NULL;
PyObject *py_addgroups = Py_None;
PyObject *py_rmgroups = Py_None;
unsigned long gid = 0;
char *groupname = NULL;
const char * const kwlist[] = { "groupname", "gid", "addgroups",
"rmgroups", NULL };
/* parse arguments */
if (!PyArg_ParseTupleAndKeywords(args, kwds,
discard_const_p(char, "s|kO!O!"),
discard_const_p(char *, kwlist),
&groupname,
&gid,
&PyList_Type,
&py_addgroups,
&PyList_Type,
&py_rmgroups)) {
goto fail;
}
tctx = init_ctx(self);
if (!tctx) {
PyErr_NoMemory();
return NULL;
}
if (py_addgroups != Py_None) {
tctx->octx->addgroups = PyList_AsStringList(tctx,
py_addgroups,
"addgroups");
if (!tctx->octx->addgroups) {
return NULL;
}
}
if (py_rmgroups != Py_None) {
tctx->octx->rmgroups = PyList_AsStringList(tctx,
py_rmgroups,
"rmgroups");
if (!tctx->octx->rmgroups) {
return NULL;
}
}
tctx->octx->name = groupname;
tctx->octx->gid = gid;
/* Modify the group within a transaction */
tctx->error = sysdb_transaction_start(tctx->sysdb);
if (tctx->error != EOK) {
PyErr_SetSssError(tctx->error);
goto fail;
}
/* groupmod */
tctx->error = groupmod(tctx, tctx->sysdb, tctx->octx);
if (tctx->error) {
/* cancel transaction */
sysdb_transaction_cancel(tctx->sysdb);
PyErr_SetSssError(tctx->error);
goto fail;
}
tctx->error = sysdb_transaction_commit(tctx->sysdb);
if (tctx->error) {
PyErr_SetSssError(tctx->error);
goto fail;
}
talloc_zfree(tctx);
Py_RETURN_NONE;
fail:
talloc_zfree(tctx);
return NULL;
}
/*** python plumbing begins here ***/
/*
* The sss.local destructor
*/
static void PySssLocalObject_dealloc(PySssLocalObject *self)
{
talloc_free(self->mem_ctx);
self->ob_type->tp_free((PyObject*) self);
}
/*
* The sss.local constructor
*/
static PyObject *PySssLocalObject_new(PyTypeObject *type,
PyObject *args,
PyObject *kwds)
{
TALLOC_CTX *mem_ctx;
PySssLocalObject *self;
char *confdb_path;
int ret;
mem_ctx = talloc_new(NULL);
if (mem_ctx == NULL) {
PyErr_NoMemory();
return NULL;
}
self = (PySssLocalObject *) type->tp_alloc(type, 0);
if (self == NULL) {
talloc_free(mem_ctx);
PyErr_NoMemory();
return NULL;
}
self->mem_ctx = mem_ctx;
confdb_path = talloc_asprintf(self->mem_ctx, "%s/%s", DB_PATH, CONFDB_FILE);
if (confdb_path == NULL) {
talloc_free(mem_ctx);
PyErr_NoMemory();
return NULL;
}
/* Connect to the conf db */
ret = confdb_init(self->mem_ctx, &self->confdb, confdb_path);
if (ret != EOK) {
talloc_free(mem_ctx);
PyErr_SetSssErrorWithMessage(ret,
"Could not initialize connection to the confdb\n");
return NULL;
}
ret = sysdb_init_domain_and_sysdb(self->mem_ctx, self->confdb, "local",
DB_PATH, &self->local, &self->sysdb);
if (ret != EOK) {
talloc_free(mem_ctx);
PyErr_SetSssErrorWithMessage(ret,
"Could not initialize connection to the sysdb\n");
return NULL;
}
self->lock = DO_LOCK;
self->unlock = DO_UNLOCK;
return (PyObject *) self;
}
/*
* sss.local object methods
*/
static PyMethodDef sss_local_methods[] = {
{ sss_py_const_p(char, "useradd"), (PyCFunction) py_sss_useradd,
METH_KEYWORDS, py_sss_useradd__doc__
},
{ sss_py_const_p(char, "userdel"), (PyCFunction) py_sss_userdel,
METH_KEYWORDS, py_sss_userdel__doc__
},
{ sss_py_const_p(char, "usermod"), (PyCFunction) py_sss_usermod,
METH_KEYWORDS, py_sss_usermod__doc__
},
{ sss_py_const_p(char, "groupadd"), (PyCFunction) py_sss_groupadd,
METH_KEYWORDS, py_sss_groupadd__doc__
},
{ sss_py_const_p(char, "groupdel"), (PyCFunction) py_sss_groupdel,
METH_KEYWORDS, py_sss_groupdel__doc__
},
{ sss_py_const_p(char, "groupmod"), (PyCFunction) py_sss_groupmod,
METH_KEYWORDS, py_sss_groupmod__doc__
},
{NULL, NULL, 0, NULL} /* Sentinel */
};
static PyMemberDef sss_local_members[] = {
{ discard_const_p(char, "lock"), T_INT,
offsetof(PySssLocalObject, lock), RO, NULL},
{ discard_const_p(char, "unlock"), T_INT,
offsetof(PySssLocalObject, unlock), RO, NULL},
{NULL, 0, 0, 0, NULL} /* Sentinel */
};
/*
* sss.local object properties
*/
static PyTypeObject pysss_local_type = {
PyObject_HEAD_INIT(NULL)
.tp_name = sss_py_const_p(char, "sss.local"),
.tp_basicsize = sizeof(PySssLocalObject),
.tp_new = PySssLocalObject_new,
.tp_dealloc = (destructor) PySssLocalObject_dealloc,
.tp_methods = sss_local_methods,
.tp_members = sss_local_members,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
.tp_doc = sss_py_const_p(char, "SSS DB manipulation"),
};
/* ==================== obfuscation python wrappers ========================*/
/*
* The sss.local object
*/
typedef struct {
PyObject_HEAD
int aes_256;
} PySssPasswordObject;
PyDoc_STRVAR(py_sss_encrypt__doc__,
"Obfuscate a password\n\n"
":param password: The password to obfuscate\n\n"
":param method: The obfuscation method\n\n");
static PyObject *py_sss_encrypt(PySssPasswordObject *self,
PyObject *args,
PyObject *kwds)
{
char *password = NULL;
int plen; /* may contain NULL bytes */
char *obfpwd = NULL;
TALLOC_CTX *tctx = NULL;
int ret;
int mode;
PyObject *retval = NULL;
/* parse arguments */
if (!PyArg_ParseTuple(args, discard_const_p(char, "s#i"),
&password, &plen, &mode)) {
return NULL;
}
tctx = talloc_new(NULL);
if (!tctx) {
PyErr_NoMemory();
return NULL;
}
ret = sss_password_encrypt(tctx, password, plen+1,
mode, &obfpwd);
if (ret != EOK) {
PyErr_SetSssError(ret);
goto fail;
}
retval = Py_BuildValue(sss_py_const_p(char, "s"), obfpwd);
if (retval == NULL) {
goto fail;
}
fail:
talloc_zfree(tctx);
return retval;
}
#if 0
PyDoc_STRVAR(py_sss_decrypt__doc__,
"Deobfuscate a password\n\n"
":param obfpwd: The password to convert back to clear text\n\n");
static PyObject *py_sss_decrypt(PySssPasswordObject *self,
PyObject *args,
PyObject *kwds)
{
char *password = NULL;
char *obfpwd = NULL;
TALLOC_CTX *tctx = NULL;
int ret;
PyObject *retval = NULL;
/* parse arguments */
if (!PyArg_ParseTuple(args, discard_const_p(char, "s"),
&obfpwd)) {
return NULL;
}
tctx = talloc_new(NULL);
if (!tctx) {
PyErr_NoMemory();
return NULL;
}
ret = sss_password_decrypt(tctx, obfpwd, &password);
if (ret != EOK) {
PyErr_SetSssError(ret);
goto fail;
}
retval = Py_BuildValue("s", password);
if (retval == NULL) {
goto fail;
}
fail:
talloc_zfree(tctx);
return retval;
}
#endif
/*
* The sss.password destructor
*/
static void PySssPasswordObject_dealloc(PySssPasswordObject *self)
{
self->ob_type->tp_free((PyObject*) self);
}
/*
* The sss.password constructor
*/
static PyObject *PySssPasswordObject_new(PyTypeObject *type,
PyObject *args,
PyObject *kwds)
{
PySssPasswordObject *self;
self = (PySssPasswordObject *) type->tp_alloc(type, 0);
if (self == NULL) {
PyErr_NoMemory();
return NULL;
}
self->aes_256 = AES_256;
return (PyObject *) self;
}
/*
* sss.password object methods
*/
static PyMethodDef sss_password_methods[] = {
{ sss_py_const_p(char, "encrypt"), (PyCFunction) py_sss_encrypt,
METH_VARARGS | METH_STATIC, py_sss_encrypt__doc__
},
#if 0
{ "decrypt", (PyCFunction) py_sss_decrypt,
METH_VARARGS | METH_STATIC, py_sss_decrypt__doc__
},
#endif
{NULL, NULL, 0, NULL} /* Sentinel */
};
/*
* sss.password object members
*/
static PyMemberDef sss_password_members[] = {
{ discard_const_p(char, "AES_256"), T_INT,
offsetof(PySssPasswordObject, aes_256), RO, NULL},
{NULL, 0, 0, 0, NULL} /* Sentinel */
};
/*
* sss.password object properties
*/
static PyTypeObject pysss_password_type = {
PyObject_HEAD_INIT(NULL)
.tp_name = sss_py_const_p(char, "sss.password"),
.tp_basicsize = sizeof(PySssPasswordObject),
.tp_new = PySssPasswordObject_new,
.tp_dealloc = (destructor) PySssPasswordObject_dealloc,
.tp_methods = sss_password_methods,
.tp_members = sss_password_members,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
.tp_doc = sss_py_const_p(char, "SSS password obfuscation"),
};
/* ==================== the sss module initialization =======================*/
/*
* Module methods
*/
static PyMethodDef module_methods[] = {
{NULL, NULL, 0, NULL} /* Sentinel */
};
/*
* Module initialization
*/
PyMODINIT_FUNC
initpysss(void)
{
PyObject *m;
if (PyType_Ready(&pysss_local_type) < 0)
return;
if (PyType_Ready(&pysss_password_type) < 0)
return;
m = Py_InitModule(discard_const_p(char, "pysss"), module_methods);
if (m == NULL)
return;
Py_INCREF(&pysss_local_type);
PyModule_AddObject(m, discard_const_p(char, "local"), (PyObject *)&pysss_local_type);
Py_INCREF(&pysss_password_type);
PyModule_AddObject(m, discard_const_p(char, "password"), (PyObject *)&pysss_password_type);
}