From 6b5044001e4b0a0caf971a2cf5f27674e0d270f4 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Thu, 17 Jul 2014 21:08:20 +0200 Subject: Implement MIT Kerberos localauth plugin The MIT Kerberos localauth pluing interface defines two different calls. The first checks if a given Kerberos principal relates to a given name of a local user (userok). The implementation lets SSSD resolve the principal and the user name and if the returned user entries both have the same UID success is returned. The second translates a given Kerberos principal to a local user name (a2l). Here SSSD is only called once to resolve the principal and the user name is returned. Resolves https://fedorahosted.org/sssd/ticket/1835 Reviewed-by: Jakub Hrozek --- Makefile.am | 10 +- src/krb5_plugin/sssd_krb5_localauth_plugin.c | 159 ++++++++++++++++++++++++++- 2 files changed, 167 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 64c017ea0..1b183d023 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2485,10 +2485,18 @@ endif if BUILD_KRB5_LOCALAUTH_PLUGIN sssd_krb5_localauth_plugin_la_SOURCES = \ - src/krb5_plugin/sssd_krb5_localauth_plugin.c + src/krb5_plugin/sssd_krb5_localauth_plugin.c \ + src/util/murmurhash3.c \ + src/util/io.c \ + src/sss_client/common.c \ + src/sss_client/nss_mc_common.c \ + src/sss_client/nss_mc_passwd.c \ + src/sss_client/nss_passwd.c sssd_krb5_localauth_plugin_la_CFLAGS = \ $(AM_CFLAGS) \ $(KRB5_CFLAGS) +sssd_krb5_localauth_plugin_la_LIBADD = \ + $(KRB5_LIBS) sssd_krb5_localauth_plugin_la_LDFLAGS = \ -avoid-version \ -module diff --git a/src/krb5_plugin/sssd_krb5_localauth_plugin.c b/src/krb5_plugin/sssd_krb5_localauth_plugin.c index 93fbbc295..83a286689 100644 --- a/src/krb5_plugin/sssd_krb5_localauth_plugin.c +++ b/src/krb5_plugin/sssd_krb5_localauth_plugin.c @@ -18,11 +18,168 @@ along with this program. If not, see . */ +#include +#include +#include +#include +#include +#include + #include +enum nss_status _nss_sss_getpwnam_r(const char *name, struct passwd *result, + char *buffer, size_t buflen, int *errnop); + +#define DEFAULT_BUFSIZE 4096 + +static krb5_error_code sss_userok(krb5_context context, + krb5_localauth_moddata data, + krb5_const_principal aname, + const char *lname) +{ + krb5_error_code kerr; + char *princ_str; + struct passwd pwd = { 0 }; + char *buffer = NULL; + size_t buflen; + enum nss_status nss_status; + int nss_errno; + uid_t princ_uid; + int ret; + + kerr = krb5_unparse_name(context, aname, &princ_str); + if (kerr != 0) { + return kerr; + } + + if (strcasecmp(princ_str, lname) == 0) { + ret = 0; + goto done; + } + + buflen = DEFAULT_BUFSIZE; + buffer = malloc(buflen); + if (buffer == NULL) { + ret = ENOMEM; + goto done; + } + + nss_status = _nss_sss_getpwnam_r(princ_str, &pwd, buffer, buflen, + &nss_errno); + if (nss_status != NSS_STATUS_SUCCESS) { + if (nss_status == NSS_STATUS_NOTFOUND) { + ret = KRB5_PLUGIN_NO_HANDLE; + } else { + ret = EIO; + } + goto done; + } + + princ_uid = pwd.pw_uid; + + nss_status = _nss_sss_getpwnam_r(lname, &pwd, buffer, buflen, &nss_errno); + if (nss_status != NSS_STATUS_SUCCESS) { + if (nss_status == NSS_STATUS_NOTFOUND) { + ret = KRB5_PLUGIN_NO_HANDLE; + } else { + ret = EIO; + } + goto done; + } + + if (princ_uid != pwd.pw_uid) { + ret = EPERM; + goto done; + } + + ret = 0; + +done: + krb5_free_unparsed_name(context, princ_str); + free(buffer); + + return ret; +} + +static krb5_error_code sss_an2ln(krb5_context context, + krb5_localauth_moddata data, + const char *type, const char *residual, + krb5_const_principal aname, char **lname_out) +{ + krb5_error_code kerr; + char *princ_str; + struct passwd pwd = { 0 }; + char *buffer = NULL; + size_t buflen; + enum nss_status nss_status; + int nss_errno; + int ret; + char *str; + + kerr = krb5_unparse_name(context, aname, &princ_str); + if (kerr != 0) { + return kerr; + } + + buflen = DEFAULT_BUFSIZE; + buffer = malloc(buflen); + if (buffer == NULL) { + ret = ENOMEM; + goto done; + } + + nss_status = _nss_sss_getpwnam_r(princ_str, &pwd, buffer, buflen, + &nss_errno); + if (nss_status != NSS_STATUS_SUCCESS) { + if (nss_status == NSS_STATUS_NOTFOUND) { + ret = KRB5_PLUGIN_NO_HANDLE; + } else { + ret = EIO; + } + goto done; + } + + str = strdup(pwd.pw_name); + if (str == NULL) { + ret = ENOMEM; + goto done; + } + + *lname_out = str; + + ret = 0; + +done: + krb5_free_unparsed_name(context, princ_str); + free(buffer); + + return ret; +} + +static void sss_freestr(krb5_context context, + krb5_localauth_moddata data, char *str) +{ + free(str); +} + krb5_error_code localauth_sssd_initvt(krb5_context context, int maj_ver, int min_ver, krb5_plugin_vtable vtable) { - return KRB5_PLUGIN_VER_NOTSUPP; + + if (maj_ver != 1 || min_ver != 1) { + return KRB5_PLUGIN_VER_NOTSUPP; + } + + krb5_localauth_vtable vt = (krb5_localauth_vtable)vtable; + + vt->init = NULL; + vt->fini = NULL; + vt->name = "sssd"; + vt->an2ln = sss_an2ln; + vt->userok = sss_userok; + vt->free_string = sss_freestr; + + return 0; } + -- cgit