diff options
author | Sumit Bose <sbose@redhat.com> | 2014-07-17 21:08:20 +0200 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2014-09-02 10:39:42 +0200 |
commit | 6b5044001e4b0a0caf971a2cf5f27674e0d270f4 (patch) | |
tree | 19adf0edd19e578245245767ee51d162d30e3555 /src | |
parent | 8a5e793a0576250da80371e53aa3e7eba15cdb63 (diff) | |
download | sssd-6b5044001e4b0a0caf971a2cf5f27674e0d270f4.tar.gz sssd-6b5044001e4b0a0caf971a2cf5f27674e0d270f4.tar.xz sssd-6b5044001e4b0a0caf971a2cf5f27674e0d270f4.zip |
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 <jhrozek@redhat.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/krb5_plugin/sssd_krb5_localauth_plugin.c | 159 |
1 files changed, 158 insertions, 1 deletions
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 <http://www.gnu.org/licenses/>. */ +#include <nss.h> +#include <sys/types.h> +#include <pwd.h> +#include <string.h> +#include <strings.h> +#include <errno.h> + #include <krb5/localauth_plugin.h> +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; } + |