From 2fa78f339460c3d5242437eb2627b56509d19750 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 29 Apr 2014 19:12:26 +0100 Subject: [PATCH] Implement "bos addkey" Implement "bos addkey". This requires the Kerberos library for the string-to-key password transformation. Signed-off-by: David Howells --- compile_pykafs.py | 5 +++ py_passwd.c | 86 ++++++++++++++++++++++++++++++++++++ py_rxgen.h | 1 + rpc-api/bos.xg | 1 + rxgen/emit_py_module.pm | 1 + suite/commands/bos/addkey.py | 77 ++++++++++++++++++++++++++++++++ 6 files changed, 171 insertions(+) create mode 100644 py_passwd.c create mode 100644 suite/commands/bos/addkey.py diff --git a/compile_pykafs.py b/compile_pykafs.py index 38206fd..aaba755 100644 --- a/compile_pykafs.py +++ b/compile_pykafs.py @@ -4,6 +4,7 @@ setup(name="kafs", version="0.1", sources = [ "afs_xg.c", "kafs.c", "afs_py.c", + "py_passwd.c", "py_rxgen.c", "py_rxconn.c", "py_rxsplit.c", @@ -13,4 +14,8 @@ setup(name="kafs", version="0.1", "-O0", "-Wp,-U_FORTIFY_SOURCE", ], + libraries = [ + "k5crypto", + "krb5" + ] )]) diff --git a/py_passwd.c b/py_passwd.c new file mode 100644 index 0000000..761caf7 --- /dev/null +++ b/py_passwd.c @@ -0,0 +1,86 @@ +/* Password-to-key service + * + * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#include +#include "structmember.h" +#include +#include "py_rxgen.h" + +/* + * Convert a string to an AFS DES key. + */ +PyObject *kafs_py_string_to_key(PyObject *_self, PyObject *args) +{ + krb5_error_code kresult; + krb5_context k5_ctx; + krb5_enctype enctype = ENCTYPE_DES_CBC_CRC; + krb5_data password; + krb5_data cellname; + krb5_data params; + krb5_keyblock key; + Py_buffer view; + PyObject *result; + char parambuf[1]; + + if (!PyArg_ParseTuple(args, "s#s#", + &password.data, &password.length, + &cellname.data, &cellname.length)) + return NULL; + + kresult = krb5_init_context(&k5_ctx); + if (kresult) + return PyErr_Format(PyExc_RuntimeError, + "Krb5: Failed to init context: %s", + krb5_get_error_message(k5_ctx, kresult)); + + password.magic = 0; + cellname.magic = 0; + + /* Tell Kerberos to use the AFS-form DES */ + parambuf[0] = 1; + params.data = parambuf; + params.length = 1; + params.magic = 0; + + kresult = krb5_c_string_to_key_with_params(k5_ctx, + enctype, + &password, + &cellname, + ¶ms, + &key); + if (kresult) { + PyErr_Format(PyExc_RuntimeError, + "Krb5: Failed to convert string to key: %s", + krb5_get_error_message(k5_ctx, kresult)); + krb5_free_context(k5_ctx); + return NULL; + } + + result = PyByteArray_FromStringAndSize("", 0); + if (!result) + goto out; + if (PyByteArray_Resize(result, key.length) == -1) + goto out_free_result; + if (PyObject_GetBuffer(result, &view, PyBUF_SIMPLE | PyBUF_WRITABLE) < 0) + goto out_free_result; + memcpy(view.buf, key.contents, key.length); + PyBuffer_Release(&view); + +out: + krb5_free_keyblock_contents(k5_ctx, &key); + krb5_free_context(k5_ctx); + return result; + +out_free_result: + Py_DECREF(result); + result = NULL; + goto out; +} diff --git a/py_rxgen.h b/py_rxgen.h index ecf7b45..eb98fe5 100644 --- a/py_rxgen.h +++ b/py_rxgen.h @@ -48,6 +48,7 @@ struct py_rx_split_call { extern PyTypeObject py_rx_connectionType; extern PyObject *kafs_py_rx_new_connection(PyObject *, PyObject *); +extern PyObject *kafs_py_string_to_key(PyObject *, PyObject *); extern int py_rxgen_initialise_members(PyObject *obj, PyObject *kw); diff --git a/rpc-api/bos.xg b/rpc-api/bos.xg index edbb8a1..443f119 100644 --- a/rpc-api/bos.xg +++ b/rpc-api/bos.xg @@ -52,6 +52,7 @@ const BZSYNTAX = 39431; const BZIO = 39432; const BZNET = 39433; const BZBADTYPE = 39434; +const BZKVNOINUSE = 39435; const BOZO_BSSIZE = 256; diff --git a/rxgen/emit_py_module.pm b/rxgen/emit_py_module.pm index 7724c44..1760eb0 100644 --- a/rxgen/emit_py_module.pm +++ b/rxgen/emit_py_module.pm @@ -52,6 +52,7 @@ sub emit_py_module() { print PYOUT "static PyMethodDef module_methods[] = {\n"; print PYOUT "\t{\"rx_new_connection\", (PyCFunction)kafs_py_rx_new_connection, METH_VARARGS, \"\" },\n"; + print PYOUT "\t{\"afs_string_to_key\", (PyCFunction)kafs_py_string_to_key, METH_VARARGS, \"\" },\n"; foreach my $def (@py_func_defs) { print PYOUT "\t{\"", $def->{name}, "\", (PyCFunction)", $def->{c_func}, ", METH_VARARGS,"; diff --git a/suite/commands/bos/addkey.py b/suite/commands/bos/addkey.py new file mode 100644 index 0000000..b18e323 --- /dev/null +++ b/suite/commands/bos/addkey.py @@ -0,0 +1,77 @@ +# +# AFS Server management toolkit: Add server keys +# -*- coding: utf-8 -*- +# + +__copyright__ = """ +Copyright (C) 2014 Red Hat, Inc. All Rights Reserved. +Written by David Howells (dhowells@redhat.com) + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public Licence version 2 as +published by the Free Software Foundation. + +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 Licence for more details. + +You should have received a copy of the GNU General Public Licence +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +""" + +from afs.exception import AFSException +from afs.argparse import * +from afs.lib.output import * +from afs.lib.time import * +import kafs +from getpass import getpass + +help = "Add a new server encryption key to the KeyFile file" + +command_arguments = [ + [ "server", get_bosserver, "rs", "" ], + [ "key", get_string, "os" "" ], + [ "kvno", get_string, "rs" "" ], + [ "cell", get_cell, "os", "" ], + [ "noauth", get_auth, "fn" ], + [ "localauth", get_auth, "fn" ], + [ "verbose", get_verbose, "fn" ], + [ "encrypt", get_dummy, "fn" ], +] + +cant_combine_arguments = [ + ( "cell", "localauth" ), + ( "noauth", "localauth" ), +] + +description = r""" +Add a new server encryption key to the KeyFile file +""" + +def main(params): + cell = params["cell"] + bos_conn = cell.open_bos_server(params["server"], params) + + if "key" in params: + passwd = params["key"] + else: + passwd = getpass("Input key: ") + passwd2 = getpass("Retype input key: ") + if passwd != passwd2: + raise RuntimeError("Input key mismatch") + + salted_passwd = kafs.afs_string_to_key(passwd, str(cell)) + key = kafs.bozo_key() + key.data = salted_passwd + + a = "" + for i in key.data: + a += "{:02x}".format(i) + verbose("Key: {:d}: ".format(len(key.data)), a, "\n") + + try: + ret = kafs.BOZO_AddKey(bos_conn, int(params["kvno"]), key) + except kafs.AbortBZKVNOINUSE: + errorf("failed to set key {:s} (kvno already used - have to remove existing kvno's before reuse)\n", params["kvno"]) -- 2.50.1