Convert machine add to kadmin API

pull/1/head
Timothy Pearson 10 years ago
parent 3d6055df7b
commit 0fbc17ac57

@ -46,34 +46,15 @@
#include <sys/time.h>
#include <errno.h>
#if 0
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <sys/un.h>
extern "C" {
#include <hdb.h>
#include <kadm5/admin.h>
#include <kadm5/private.h>
#include <kadm5/kadm5-private.h>
#else
#include <kadm5/admin.h>
extern "C" {
// The following declaration was taken from hdb-protos.h
const char *
hdb_db_dir (krb5_context /*context*/);
// The following declaration was taken from kadm5-private.h
kadm5_ret_t
kadm5_s_init_with_password_ctx (
krb5_context /*context*/,
const char */*client_name*/,
const char */*password*/,
const char */*service_name*/,
kadm5_config_params */*realm_params*/,
unsigned long /*struct_version*/,
unsigned long /*api_version*/,
void **/*server_handle*/);
}
#endif
}
#include "libtdeldap.h"
#include "ldaplogindlg.h"
@ -90,6 +71,9 @@
// This assumes Debian!
#define KRB5_FILE "/etc/krb5.conf"
//#define KRB5_ANK_RANDOM_PASSWORD_LENGTH 1024
#define KRB5_ANK_RANDOM_PASSWORD_LENGTH 512
#define NSSWITCH_FILE "/etc/nsswitch.conf"
#define PAMD_DIRECTORY "/etc/pam.d/"
@ -137,6 +121,19 @@ bool fileExists(const char* filename) {
}
}
static kadm5_ret_t kadm5_get_default_principal_info(krb5_context context, void* handle, krb5_principal princ, kadm5_principal_ent_t def) {
kadm5_ret_t ret;
krb5_principal def_principal;
krb5_const_realm realm = krb5_principal_get_realm(context, princ);
ret = krb5_make_principal(context, &def_principal, realm, "default", NULL);
if (ret) {
return ret;
}
ret = kadm5_get_principal(handle, def_principal, def, KADM5_PRINCIPAL_NORMAL_MASK);
krb5_free_principal(context, def_principal);
return ret;
}
LDAPManager::LDAPManager(TQString realm, TQString host, TQObject *parent, const char *name) : TQObject(parent, name), m_realm(realm), m_host(host), m_port(0), m_creds(0), m_ldap(0), m_krb5admHandle(0), m_krb5admKeytabFilename(0), m_krb5admRealmName(0)
{
TQStringList domainChunks = TQStringList::split(".", realm.lower());
@ -196,10 +193,25 @@ TQString LDAPManager::realm() {
return m_realm;
}
LDAPCredentials LDAPManager::currentLDAPCredentials() {
LDAPCredentials LDAPManager::currentLDAPCredentials(bool inferGSSAPIData) {
if (m_creds) {
if (inferGSSAPIData) {
LDAPCredentials credentials = *m_creds;
if ((credentials.username == "") && (credentials.password == "")) {
// Probably GSSAPI
// Get active ticket principal...
KerberosTicketInfoList tickets = LDAPManager::getKerberosTicketList();
TQStringList principalParts = TQStringList::split("@", tickets[0].cachePrincipal, false);
credentials.username = principalParts[0];
credentials.realm = principalParts[1];
credentials.use_gssapi = true;
}
return credentials;
}
else {
return *m_creds;
}
}
else {
return LDAPCredentials();
}
@ -346,8 +358,9 @@ int LDAPManager::bind(TQString* errstr) {
return -1;
}
struct berval anoncred;
anoncred.bv_val = "";
anoncred.bv_len = strlen("");
TQCString anonpass = "";
anoncred.bv_val = anonpass.data();
anoncred.bv_len = anonpass.length();
retcode = ldap_sasl_bind_s(ldapconn, "", mechanism, &anoncred, NULL, NULL, NULL);
if (retcode == LDAP_SUCCESS ) {
// Look for the DN for the specified user
@ -1127,7 +1140,7 @@ TQString LDAPManager::readFullLineFromPtyProcess(PtyProcess* proc) {
return result;
}
int LDAPManager::bindKAdmin(LDAPUserInfo user, TQString *errstr) {
int LDAPManager::bindKAdmin(TQString *errstr) {
int retcode = 1;
kadm5_ret_t krb5adm_ret;
@ -1186,7 +1199,7 @@ int LDAPManager::bindKAdmin(LDAPUserInfo user, TQString *errstr) {
krb5adm_ret = krb5_init_context(&m_krb5admContext);
if (krb5adm_ret) {
if (errstr) *errstr = TQString("%1<p>Details:<br>Failed to execute kadm5_init_krb5_context (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret);
if (errstr) *errstr = i18n("%1<p>Details:<br>Failed to execute kadm5_init_krb5_context (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret);
}
else {
if (use_local_socket) {
@ -1278,7 +1291,7 @@ int LDAPManager::setPasswordForUser(LDAPUserInfo user, TQString *errstr) {
int retcode;
kadm5_ret_t krb5adm_ret;
retcode = bindKAdmin(user, errstr);
retcode = bindKAdmin(errstr);
if (retcode == 0) {
retcode = 1;
krb5_principal user_kadm5_principal;
@ -1301,6 +1314,7 @@ int LDAPManager::setPasswordForUser(LDAPUserInfo user, TQString *errstr) {
}
unbindKAdmin();
unbind(true); // Using kadmin can disrupt our LDAP connection
}
return retcode;
@ -1833,6 +1847,147 @@ int LDAPManager::addMachineInfo(LDAPMachineInfo machine, TQString *errstr) {
return -1;
}
else {
int retcode;
kadm5_ret_t krb5adm_ret;
int i;
char* password = NULL;
retcode = bindKAdmin(errstr);
if (retcode == 0) {
retcode = 1;
bool generate_password;
if (machine.newPassword == "") {
generate_password = true;
}
else {
generate_password = false;
password = strdup(machine.newPassword.data());
}
LDAPCredentials admincreds = currentLDAPCredentials(true);
TQString hoststring = "host/" + machine.name + "." + admincreds.realm.lower();
// Construct and add new principal record
kadm5_principal_ent_rec principal_record;
kadm5_principal_ent_rec default_record;
kadm5_principal_ent_rec *default_entry = NULL;
krb5_principal principal_entry = NULL;
int mask = 0;
memset(&principal_record, 0, sizeof(principal_record));
krb5adm_ret = krb5_parse_name(m_krb5admContext, hoststring.ascii(), &principal_entry);
if (krb5adm_ret) {
if (errstr) *errstr = i18n("%1<p>Details:<br>Failed to execute krb5_parse_name (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret);
}
principal_record.principal = principal_entry;
mask |= KADM5_PRINCIPAL;
default_entry = &default_record;
krb5adm_ret = kadm5_get_default_principal_info(m_krb5admContext, m_krb5admHandle, principal_entry, default_entry);
if (krb5adm_ret) {
default_entry = NULL;
if (errstr) *errstr = i18n("%1<p>Details:<br>Failed to execute kadm5_get_default_principal_info (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret);
}
else {
// Use defaults
principal_record.max_life = default_entry->max_life;
principal_record.max_renewable_life = default_entry->max_renewable_life;
principal_record.princ_expire_time = default_entry->princ_expire_time;
principal_record.pw_expiration = default_entry->pw_expiration;
principal_record.attributes = default_entry->attributes & ~KRB5_KDB_DISALLOW_ALL_TIX;
principal_record.policy = strdup(default_entry->policy);
if (generate_password) {
const char charset[] =
"@$%&*()-+=:,/<>?0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
const size_t max_index = (sizeof(charset) - 2);
TQFile randomNode("/dev/urandom");
if (randomNode.open(IO_ReadOnly)) {
password = (char*)malloc(sizeof(char) * KRB5_ANK_RANDOM_PASSWORD_LENGTH);
if (password) {
if (randomNode.readBlock(password, KRB5_ANK_RANDOM_PASSWORD_LENGTH) < KRB5_ANK_RANDOM_PASSWORD_LENGTH) {
free(password);
password = NULL;
}
else {
for (i = 0; i < KRB5_ANK_RANDOM_PASSWORD_LENGTH - 1; i++) {
while ((unsigned char)password[i] > max_index) {
password[i] -= max_index;
}
password[i] = charset[(int)password[i]];
}
password[i] = 0;
}
}
randomNode.close();
}
if (password) {
principal_record.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
mask |= KADM5_ATTRIBUTES;
}
else {
if (errstr) *errstr = i18n("Unable to generate random password");
}
}
if (password) {
krb5adm_ret = kadm5_create_principal(m_krb5admHandle, &principal_record, mask, password);
if (krb5adm_ret) {
if (errstr) *errstr = i18n("%1<p>Details:<br>Failed to execute kadm5_create_principal (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret);
}
else {
if (generate_password) {
krb5_keyblock *new_keys;
int key_count;
krb5adm_ret = kadm5_randkey_principal(m_krb5admHandle, principal_entry, &new_keys, &key_count);
if (krb5adm_ret) {
key_count = 0;
}
for (i = 0; i < key_count; i++) {
krb5_free_keyblock_contents(m_krb5admContext, &new_keys[i]);
}
if (key_count > 0) {
free(new_keys);
}
kadm5_get_principal(m_krb5admHandle, principal_entry, &principal_record, KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES);
krb5_free_principal(m_krb5admContext, principal_entry);
principal_entry = principal_record.principal;
principal_record.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX);
principal_record.kvno = 1;
krb5adm_ret = kadm5_modify_principal(m_krb5admHandle, &principal_record, KADM5_ATTRIBUTES | KADM5_KVNO);
if (krb5adm_ret) {
if (errstr) *errstr = i18n("%1<p>Details:<br>Failed to execute kadm5_modify_principal (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret);
}
else {
retcode = 0;
}
}
else {
retcode = 0;
}
}
}
}
kadm5_free_principal_ent(m_krb5admHandle, &principal_record);
if (default_entry) {
kadm5_free_principal_ent(m_krb5admHandle, default_entry);
}
if (password) {
free(password);
}
unbindKAdmin();
unbind(true); // Using kadmin can disrupt our LDAP connection
}
return retcode;
#if 0
// Use Kerberos kadmin to actually add the machine
LDAPCredentials admincreds = currentLDAPCredentials();
if ((admincreds.username == "") && (admincreds.password == "")) {
@ -1950,6 +2105,7 @@ int LDAPManager::addMachineInfo(LDAPMachineInfo machine, TQString *errstr) {
if (errstr) *errstr = "Internal error. Verify that kadmin exists and can be executed.";
return 1; // Failure
#endif
}
}

@ -521,7 +521,7 @@ class LDAPManager : public TQObject {
int exportKeytabForPrincipal(TQString principal, TQString fileName, TQString *errstr=0);
LDAPCredentials currentLDAPCredentials();
LDAPCredentials currentLDAPCredentials(bool inferGSSAPIData=false);
int moveKerberosEntries(TQString newSuffix, TQString* errstr=0);
int writeCertificateFileIntoDirectory(TQByteArray cert, TQString attr, TQString* errstr=0);
@ -589,7 +589,7 @@ class LDAPManager : public TQObject {
static int unbondRealm(LDAPRealmConfig realmcfg, TQString adminUserName, const char * adminPassword, TQString adminRealm, TQString *errstr=0);
private:
int bindKAdmin(LDAPUserInfo user, TQString *errstr=0);
int bindKAdmin(TQString *errstr=0);
int unbindKAdmin(TQString *errstr=0);
LDAPUserInfo parseLDAPUserRecord(LDAPMessage* entry);
LDAPGroupInfo parseLDAPGroupRecord(LDAPMessage* entry);

Loading…
Cancel
Save