sssd_krb5_localauth_plugin.c revision 2ca45dfa0144fea08bd360dafded57bc90111e68
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose/*
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose Authors:
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose Sumit Bose <sbose@redhat.com>
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose Copyright (C) 2014 Red Hat
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose This program is free software; you can redistribute it and/or modify
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose it under the terms of the GNU General Public License as published by
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose the Free Software Foundation; either version 3 of the License, or
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose (at your option) any later version.
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose This program is distributed in the hope that it will be useful,
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose but WITHOUT ANY WARRANTY; without even the implied warranty of
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose GNU General Public License for more details.
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose You should have received a copy of the GNU General Public License
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose along with this program. If not, see <http://www.gnu.org/licenses/>.
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose*/
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose#include <nss.h>
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose#include <sys/types.h>
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose#include <pwd.h>
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose#include <string.h>
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose#include <strings.h>
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose#include <errno.h>
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose#include <krb5/localauth_plugin.h>
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Boseenum nss_status _nss_sss_getpwnam_r(const char *name, struct passwd *result,
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose char *buffer, size_t buflen, int *errnop);
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose#define DEFAULT_BUFSIZE 4096
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bosestatic krb5_error_code sss_userok(krb5_context context,
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose krb5_localauth_moddata data,
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose krb5_const_principal aname,
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose const char *lname)
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose{
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose krb5_error_code kerr;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose char *princ_str;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose struct passwd pwd = { 0 };
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose char *buffer = NULL;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose size_t buflen;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose enum nss_status nss_status;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose int nss_errno;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose uid_t princ_uid;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose int ret;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose kerr = krb5_unparse_name(context, aname, &princ_str);
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose if (kerr != 0) {
2ca45dfa0144fea08bd360dafded57bc90111e68Sumit Bose ret = kerr;
2ca45dfa0144fea08bd360dafded57bc90111e68Sumit Bose goto done;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose }
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose if (strcasecmp(princ_str, lname) == 0) {
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose ret = 0;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose goto done;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose }
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose buflen = DEFAULT_BUFSIZE;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose buffer = malloc(buflen);
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose if (buffer == NULL) {
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose ret = ENOMEM;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose goto done;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose }
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose nss_status = _nss_sss_getpwnam_r(princ_str, &pwd, buffer, buflen,
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose &nss_errno);
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose if (nss_status != NSS_STATUS_SUCCESS) {
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose if (nss_status == NSS_STATUS_NOTFOUND) {
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose ret = KRB5_PLUGIN_NO_HANDLE;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose } else {
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose ret = EIO;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose }
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose goto done;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose }
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose princ_uid = pwd.pw_uid;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose nss_status = _nss_sss_getpwnam_r(lname, &pwd, buffer, buflen, &nss_errno);
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose if (nss_status != NSS_STATUS_SUCCESS) {
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose if (nss_status == NSS_STATUS_NOTFOUND) {
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose ret = KRB5_PLUGIN_NO_HANDLE;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose } else {
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose ret = EIO;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose }
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose goto done;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose }
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose if (princ_uid != pwd.pw_uid) {
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose ret = EPERM;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose goto done;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose }
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose ret = 0;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bosedone:
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose krb5_free_unparsed_name(context, princ_str);
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose free(buffer);
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
2ca45dfa0144fea08bd360dafded57bc90111e68Sumit Bose if (ret != 0) {
2ca45dfa0144fea08bd360dafded57bc90111e68Sumit Bose return KRB5_PLUGIN_NO_HANDLE;
2ca45dfa0144fea08bd360dafded57bc90111e68Sumit Bose }
2ca45dfa0144fea08bd360dafded57bc90111e68Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose return ret;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose}
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bosestatic krb5_error_code sss_an2ln(krb5_context context,
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose krb5_localauth_moddata data,
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose const char *type, const char *residual,
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose krb5_const_principal aname, char **lname_out)
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose{
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose krb5_error_code kerr;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose char *princ_str;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose struct passwd pwd = { 0 };
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose char *buffer = NULL;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose size_t buflen;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose enum nss_status nss_status;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose int nss_errno;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose int ret;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose char *str;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose kerr = krb5_unparse_name(context, aname, &princ_str);
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose if (kerr != 0) {
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose return kerr;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose }
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose buflen = DEFAULT_BUFSIZE;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose buffer = malloc(buflen);
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose if (buffer == NULL) {
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose ret = ENOMEM;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose goto done;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose }
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose nss_status = _nss_sss_getpwnam_r(princ_str, &pwd, buffer, buflen,
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose &nss_errno);
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose if (nss_status != NSS_STATUS_SUCCESS) {
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose if (nss_status == NSS_STATUS_NOTFOUND) {
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose ret = KRB5_PLUGIN_NO_HANDLE;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose } else {
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose ret = EIO;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose }
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose goto done;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose }
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
cc98e19b424861c2a7fd91e0d657d82c1dbf3059Pavel Reichl if (pwd.pw_name == NULL) {
cc98e19b424861c2a7fd91e0d657d82c1dbf3059Pavel Reichl ret = EINVAL;
cc98e19b424861c2a7fd91e0d657d82c1dbf3059Pavel Reichl goto done;
cc98e19b424861c2a7fd91e0d657d82c1dbf3059Pavel Reichl }
cc98e19b424861c2a7fd91e0d657d82c1dbf3059Pavel Reichl
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose str = strdup(pwd.pw_name);
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose if (str == NULL) {
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose ret = ENOMEM;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose goto done;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose }
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose *lname_out = str;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose ret = 0;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bosedone:
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose krb5_free_unparsed_name(context, princ_str);
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose free(buffer);
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose return ret;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose}
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bosestatic void sss_freestr(krb5_context context,
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose krb5_localauth_moddata data, char *str)
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose{
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose free(str);
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose}
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bosekrb5_error_code
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Boselocalauth_sssd_initvt(krb5_context context, int maj_ver, int min_ver,
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose krb5_plugin_vtable vtable)
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose{
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose if (maj_ver != 1 || min_ver != 1) {
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose return KRB5_PLUGIN_VER_NOTSUPP;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose }
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose krb5_localauth_vtable vt = (krb5_localauth_vtable)vtable;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose vt->init = NULL;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose vt->fini = NULL;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose vt->name = "sssd";
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose vt->an2ln = sss_an2ln;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose vt->userok = sss_userok;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose vt->free_string = sss_freestr;
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose return 0;
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose}
6b5044001e4b0a0caf971a2cf5f27674e0d270f4Sumit Bose