Example #1
0
static krb5_error_code
check_an2ln(krb5_context context,
	    krb5_const_principal principal,
	    const char *luser,
	    krb5_boolean *result)
{
    krb5_error_code ret;
    char *lname;

#if 0
    /* XXX Should we make this an option? */
    /* multi-component principals can never match */
    if (krb5_principal_get_comp_string(context, principal, 1) != NULL) {
	*result =  FALSE;
	return 0;
    }
#endif

    lname = malloc(strlen(luser) + 1);
    if (lname == NULL)
	return krb5_enomem(context);
    ret = krb5_aname_to_localname(context, principal, strlen(luser)+1, lname);
    if (ret)
	goto out;
    if (strcmp(lname, luser) == 0)
	*result = TRUE;
    else
	*result = FALSE;

out:
    free(lname);
    return 0;

}
Example #2
0
/*
 * Determine whether principal is authorized to log in as luser according to
 * aname-to-localname translation.  Return ACCEPT if principal translates to
 * luser or PASS if it does not.
 */
static enum result
an2ln_ok(krb5_context context, krb5_principal principal, const char *luser)
{
    krb5_error_code ret;
    char kuser[MAX_USERNAME];

    ret = krb5_aname_to_localname(context, principal, sizeof(kuser), kuser);
    if (ret != 0)
        return PASS;
    return (strcmp(kuser, luser) == 0) ? ACCEPT : PASS;
}
Example #3
0
int
ssh_krb5_kuserok(krb5_context krb5_ctx, krb5_principal krb5_user, const char *client)
{
	if (options.use_kuserok)
		return krb5_kuserok(krb5_ctx, krb5_user, client);
	else {
		char kuser[65];

		if (krb5_aname_to_localname(krb5_ctx, krb5_user, sizeof(kuser), kuser))
			return 0;
		return strcmp(kuser, client) == 0;
	}
}
Example #4
0
OM_uint32 GSSAPI_CALLCONV
_gsskrb5_pname_to_uid(OM_uint32 *minor_status,
                      const gss_name_t pname,
                      const gss_OID mech_type,
                      uid_t *uidp)
{
#ifdef NO_LOCALNAME
    *minor_status = KRB5_NO_LOCALNAME;
    return GSS_S_FAILURE;
#else
    krb5_error_code ret;
    krb5_context context;
    krb5_const_principal princ = (krb5_const_principal)pname;
    char localname[256];
#ifdef POSIX_GETPWNAM_R
    char pwbuf[2048];
    struct passwd pw, *pwd;
#else
    struct passwd *pwd;
#endif

    GSSAPI_KRB5_INIT(&context);

    *minor_status = 0;

    ret = krb5_aname_to_localname(context, princ,
                                  sizeof(localname), localname);
    if (ret != 0) {
        *minor_status = ret;
        return GSS_S_FAILURE;
    }

#ifdef POSIX_GETPWNAM_R
    if (getpwnam_r(localname, &pw, pwbuf, sizeof(pwbuf), &pwd) != 0) {
        *minor_status = KRB5_NO_LOCALNAME;
        return GSS_S_FAILURE;
    }
#else
    pwd = getpwnam(localname);
#endif

    if (pwd == NULL) {
        *minor_status = KRB5_NO_LOCALNAME;
        return GSS_S_FAILURE;
    }

    *uidp = pwd->pw_uid;

    return GSS_S_COMPLETE;
#endif /* NO_LOCALNAME */
}
Example #5
0
OM_uint32
_gsskrb5_pname_to_uid(OM_uint32 *minor_status, const gss_name_t pname,
    const gss_OID mech, uid_t *uidp)
{
	krb5_context context;
	krb5_const_principal name = (krb5_const_principal) pname;
	krb5_error_code kret;
	char lname[MAXLOGNAME + 1], buf[1024], *bufp;
	struct passwd pwd, *pw;
	size_t buflen;
	int error;
	OM_uint32 ret;
	static size_t buflen_hint = 1024;

	GSSAPI_KRB5_INIT (&context);

	kret = krb5_aname_to_localname(context, name, sizeof(lname), lname);
	if (kret) {
		*minor_status = kret;
		return (GSS_S_FAILURE);
	}

	*minor_status = 0;
	buflen = buflen_hint;
	for (;;) {
		pw = NULL;
		bufp = buf;
		if (buflen > sizeof(buf))
			bufp = malloc(buflen);
		if (bufp == NULL)
			break;
		error = getpwnam_r(lname, &pwd, bufp, buflen, &pw);
		if (error != ERANGE)
			break;
		if (buflen > sizeof(buf))
			free(bufp);
		buflen += 1024;
		if (buflen > buflen_hint)
			buflen_hint = buflen;
	}
	if (pw) {
		*uidp = pw->pw_uid;
		ret = GSS_S_COMPLETE;
	} else {
		ret = GSS_S_FAILURE;
	}
	if (bufp != NULL && buflen > sizeof(buf))
		free(bufp);
	return (ret);
}
Example #6
0
int check(const char* principal) {
    krb5_context ctx = NULL;
    krb5_principal princ = NULL;
    krb5_error_code code;
    char lname[MAX_USERNAME];
    int result = 0;

    code = krb5_init_context(&ctx);
    if (code != 0) {
        fprintf(stderr, "%s: error in krb5_init_context: %d\n", prog, code);
        result = 1;
        goto end;
    }

    code = krb5_parse_name(ctx, principal, &princ);
    if (code != 0) {
        fprintf(stderr, "%s: error in krb5_parse_name: %d\n", prog, code);
        result = 1;
        goto end;
    }

    code = krb5_aname_to_localname(ctx, princ, MAX_USERNAME-1, lname);
    if (code != 0) {
        fprintf(stderr, "%s: error in krb5_aname_to_localname: %d\n",
                prog,
                code);
        result = 1;
        goto end;
    }

    if (strcmp(lname, "user") != 0) {
        fprintf(stderr, "%s: error, got %s, expected %s\n", prog, lname, "user");
        result = 1;
        goto end;
    }

    fprintf(stderr, "%s: ok\n", prog);

end:
    if (princ != NULL) {
        krb5_free_principal(ctx, princ);
    }
    if (ctx != NULL) {
        krb5_free_context(ctx);
    }
    return result;
}
Example #7
0
static void
test_alname(krb5_context context, krb5_const_realm realm,
	    const char *user, const char *inst, 
	    const char *localuser, int ok)
{
    krb5_principal p;
    char localname[1024];
    krb5_error_code ret;
    char *princ;

    ret = krb5_make_principal(context, &p, realm, user, inst, NULL);
    if (ret)
	krb5_err(context, 1, ret, "krb5_build_principal");

    ret = krb5_unparse_name(context, p, &princ);
    if (ret)
	krb5_err(context, 1, ret, "krb5_unparse_name");

    ret = krb5_aname_to_localname(context, p, sizeof(localname), localname);
    krb5_free_principal(context, p);
    free(princ);
    if (ret) {
	if (!ok)
	    return;
	krb5_err(context, 1, ret, "krb5_aname_to_localname: %s -> %s", 
		 princ, localuser);
    }

    if (strcmp(localname, localuser) != 0) {
	if (ok)
	    errx(1, "compared failed %s != %s (should have succeded)", 
		 localname, localuser);
    } else {
	if (!ok)
	    errx(1, "compared failed %s == %s (should have failed)", 
		 localname, localuser);
    }
    
}
Example #8
0
char *kerberos_login (char *user,char *authuser,int argc,char *argv[])
{
  krb5_context ctx;
  krb5_principal prnc;
  char kuser[NETMAXUSER];
  char *ret = NIL;
				/* make a context */
  if (!krb5_init_context (&ctx)) {
				/* build principal */
    if (!krb5_parse_name (ctx,authuser,&prnc)) {
				/* can get local name for this principal? */
      if (!krb5_aname_to_localname (ctx,prnc,NETMAXUSER-1,kuser)) {
				/* yes, local name permitted login as user?  */
	if (authserver_login (user,kuser,argc,argv) ||
	    authserver_login (lcase (user),kuser,argc,argv))
	  ret = myusername ();	/* yes, return user name */
      }
      krb5_free_principal (ctx,prnc);
    }
    krb5_free_context (ctx);	/* finished with context */
  }
  return ret;
}
Example #9
0
int auks_cred_init(auks_cred_t * credential, char *data, size_t length)
{
	int fstatus = AUKS_ERROR ;

	char *tmp_string = NULL;
	size_t tmp_size = 0;

	/* kerberos related variables */
	krb5_error_code err_code;
	krb5_context context;
	krb5_auth_context auth_context;
	krb5_data kdata;
	krb5_creds **creds;
	krb5_replay_data krdata;

	char username[AUKS_PRINCIPAL_MAX_LENGTH + 1];
	struct passwd user_pwent;
	struct passwd *p_pwent;
	size_t pwnam_buffer_length = sysconf(_SC_GETPW_R_SIZE_MAX);
	char pwnam_buffer[pwnam_buffer_length];

	credential->info.principal[0] = '\0';
	credential->info.uid = AUKS_CRED_INVALID_UID;

	credential->info.starttime = AUKS_CRED_INVALID_TIME;
	credential->info.endtime = AUKS_CRED_INVALID_TIME;
	credential->info.renew_till = AUKS_CRED_INVALID_TIME;

	credential->info.addressless = 1;

	credential->data[1] = '\0';
	credential->length = 0;
	credential->max_length = AUKS_CRED_DATA_MAX_LENGTH;
	credential->status = AUKS_SUCCESS;

	/* check input buffer length versus auks credential internal buffer */
	/* max length */
	if ((unsigned int) length > (unsigned int) credential->max_length) {
		auks_error("input buffer is bigger than auks credential internal "
			   "buffer (%u versus %u)",length, credential->max_length);
		fstatus = AUKS_ERROR_CRED_INIT_BUFFER_TOO_LARGE ;
		goto exit;
	}

	/* extract informations from buffer */
	if (data == NULL) {
		auks_error("input buffer is NULL");
		fstatus = AUKS_ERROR_CRED_INIT_BUFFER_IS_NULL ;
		goto exit;
	}
	fstatus = AUKS_ERROR ;

	/* initialize kerberos context */
	err_code = krb5_init_context(&context);
	if (err_code) {
		auks_error("unable to initialize kerberos context : %s",
			   error_message(err_code));
		fstatus = AUKS_ERROR_CRED_INIT_KRB_CTX_INIT ;
		goto exit;
	}
	auks_log("kerberos context successfully initialized");

	/* initialize a nullified kerberos authentication context 
	   in order to decode credential from buffer */
	err_code =
		krb5_auth_con_init(context,&auth_context);
	if (err_code) {
		auks_error("unable to initialize connection "
			   "authentication context : %s",
			   error_message(err_code));
		fstatus = AUKS_ERROR_CRED_INIT_KRB_AUTH_CTX_INIT ;
		goto ctx_exit;
	}
	
	/* clear kerberos authentication context flags */
	krb5_auth_con_setflags(context,auth_context,0);
	/* set a kerberos data structure with input buffer */
	kdata.data = data ;
	kdata.length = (unsigned int) length ;

	/* build kerberos credential structure using this data structure */
	err_code = krb5_rd_cred(context,auth_context,&kdata, &creds,&krdata);
	if (err_code) {
		auks_error("unable to deserialize input buffer credential : %s",
			   error_message(err_code));
		fstatus = AUKS_ERROR_CRED_INIT_KRB_RD_BUFFER ;
		goto auth_ctx_exit;
	}

	auks_log("input buffer credential successfully unserialized");
	err_code = krb5_unparse_name_ext(context,(*creds)->client,&tmp_string,
					 (unsigned int *) &tmp_size);
	if (err_code) {
		auks_error("unable to unparse principal : %s",
			   error_message(err_code));
		fstatus = AUKS_ERROR_CRED_INIT_KRB_RD_PRINC ;
		goto creds_exit;
	} else if (tmp_size > AUKS_PRINCIPAL_MAX_LENGTH) {
		auks_error("unable to unparse principal : %s",
			   "principal is too long (more than %d characters)",
			   AUKS_PRINCIPAL_MAX_LENGTH);
		free(tmp_string);
		fstatus = AUKS_ERROR_CRED_INIT_KRB_PRINC_TOO_LONG ;
		goto creds_exit;
	}
	auks_log("principal successfully unparse");
	memcpy(credential->info.principal,tmp_string,tmp_size);
	credential->info.principal[tmp_size] = '\0';
	/* associated username from principal */
	err_code = krb5_aname_to_localname(context,(*creds)->client,
					   AUKS_PRINCIPAL_MAX_LENGTH,username);
	if (err_code) {
		auks_error("unable to get username from principal %s : %s",
			   credential->info.principal,error_message(err_code));
		fstatus = AUKS_ERROR_CRED_INIT_KRB_PRINC_TO_UNAME ;
		goto string_exit;
	}

	/* associated uid from username */
	fstatus = getpwnam_r(username,&user_pwent,pwnam_buffer,
			     pwnam_buffer_length,&p_pwent) ;
	if (fstatus) {
		auks_log("unable to get %s pwnam entry : %s",username,
			 strerror(fstatus)) ;
		fstatus = AUKS_ERROR_CRED_INIT_GETPWNAM ;
		goto string_exit;
	}

	/* uid information */
	credential->info.uid = user_pwent.pw_uid;

	credential->info.starttime = (time_t) (*creds)->times.starttime ;
	credential->info.endtime = (time_t) (*creds)->times.endtime ;
	credential->info.renew_till = (time_t) (*creds)->times.renew_till ;

	/* addresslessness */
	if (((*creds)->addresses) != NULL)
		credential->info.addressless = 0;

	/* duplicate input buffer */
	credential->length = (unsigned int) length;
	memcpy(credential->data,data,(unsigned int) length);

	fstatus = AUKS_SUCCESS;

string_exit:
	free(tmp_string);

creds_exit:
	krb5_free_creds(context,*creds);
	free(creds);

auth_ctx_exit:
	krb5_auth_con_free(context,auth_context);

ctx_exit:
	krb5_free_context(context);

exit:
	/* if valid buffer, store it */
	if (fstatus != 0) {
		/* bad credential buffer in input, clean this auks credential */
		auks_cred_free_contents(credential);
	}
	
	return fstatus;
}
Example #10
0
krb5_boolean KRB5_CALLCONV
krb5_kuserok(krb5_context context, krb5_principal principal, const char *luser)
{
    struct stat sbuf;
    struct passwd *pwd;
    char pbuf[MAXPATHLEN];
    krb5_boolean isok = FALSE;
    FILE *fp;
    char kuser[MAX_USERNAME];
    char *princname;
    char linebuf[BUFSIZ];
    char *newline;
    int gobble;

    /* no account => no access */
    char pwbuf[BUFSIZ];
    struct passwd pwx;
    if (k5_getpwnam_r(luser, &pwx, pwbuf, sizeof(pwbuf), &pwd) != 0)
	return(FALSE);
    (void) strncpy(pbuf, pwd->pw_dir, sizeof(pbuf) - 1);
    pbuf[sizeof(pbuf) - 1] = '\0';
    (void) strncat(pbuf, "/.k5login", sizeof(pbuf) - 1 - strlen(pbuf));

    if (access(pbuf, F_OK)) {	 /* not accessible */
	/*
	 * if he's trying to log in as himself, and there is no .k5login file,
	 * let him.  To find out, call
	 * krb5_aname_to_localname to convert the principal to a name
	 * which we can string compare. 
	 */
	if (!(krb5_aname_to_localname(context, principal,
				      sizeof(kuser), kuser))
	    && (strcmp(kuser, luser) == 0)) {
	    return(TRUE);
	}
    }
    if (krb5_unparse_name(context, principal, &princname))
	return(FALSE);			/* no hope of matching */

    /* open ~/.k5login */
    if ((fp = fopen(pbuf, "r")) == NULL) {
	free(princname);
	return(FALSE);
    }
    set_cloexec_file(fp);
    /*
     * For security reasons, the .k5login file must be owned either by
     * the user himself, or by root.  Otherwise, don't grant access.
     */
    if (fstat(fileno(fp), &sbuf)) {
	fclose(fp);
	free(princname);
	return(FALSE);
    }
    if (sbuf.st_uid != pwd->pw_uid && !FILE_OWNER_OK(sbuf.st_uid)) {
	fclose(fp);
	free(princname);
	return(FALSE);
    }

    /* check each line */
    while (!isok && (fgets(linebuf, BUFSIZ, fp) != NULL)) {
	/* null-terminate the input string */
	linebuf[BUFSIZ-1] = '\0';
	newline = NULL;
	/* nuke the newline if it exists */
	if ((newline = strchr(linebuf, '\n')))
	    *newline = '\0';
	if (!strcmp(linebuf, princname)) {
	    isok = TRUE;
	    continue;
	}
	/* clean up the rest of the line if necessary */
	if (!newline)
	    while (((gobble = getc(fp)) != EOF) && gobble != '\n');
    }
    free(princname);
    fclose(fp);
    return(isok);
}
Example #11
0
/*
 * Verify the user authorization.  Call krb5_kuserok if this is a local
 * account, or do the krb5_aname_to_localname verification if ignore_k5login
 * was requested.  For non-local accounts, the principal must match the
 * authentication identity.
 */
int
pamk5_authorized(struct pam_args *args)
{
    struct context *ctx;
    krb5_context c;
    struct passwd *pwd;
    char kuser[65];             /* MAX_USERNAME == 65 (MIT Kerberos 1.4.1). */

    if (args == NULL || args->ctx == NULL || args->ctx->context == NULL)
        return PAM_SERVICE_ERR;
    ctx = args->ctx;
    if (ctx->name == NULL)
        return PAM_SERVICE_ERR;
    c = ctx->context;

    /*
     * If alt_auth_map was set, authorize the user if the authenticated
     * principal matches the mapped principal.  alt_auth_map essentially
     * serves as a supplemental .k5login.
     */
    if (args->alt_auth_map != NULL) {
        char *mapped;
        char *authed;
        int retval;
        krb5_principal princ;

        if (pamk5_map_principal(args, ctx->name, &mapped) != PAM_SUCCESS)
            return PAM_SERVICE_ERR;
        retval = krb5_parse_name(c, mapped, &princ);
        if (retval != 0) {
            free(mapped);
            return PAM_SERVICE_ERR;
        }
        free(mapped);
        retval = krb5_unparse_name(c, princ, &mapped);
        if (retval != 0)
            return PAM_SERVICE_ERR;
        retval = krb5_unparse_name(c, ctx->princ, &authed);
        if (retval != 0) {
            free(mapped);
            return PAM_SERVICE_ERR;
        }
        if (strcmp(authed, mapped) == 0) {
            free(authed);
            free(mapped);
            return PAM_SUCCESS;
        }
        free(authed);
        free(mapped);
    }

    /*
     * If the name to which we're authenticating contains @ (is fully
     * qualified), it must match the principal exactly.
     */
    if (strchr(ctx->name, '@') != NULL) {
        char *principal;
        int retval;

        retval = krb5_unparse_name(c, ctx->princ, &principal);
        if (retval != 0)
            return PAM_SERVICE_ERR;
        if (strcmp(principal, ctx->name) != 0) {
            free(principal);
            return PAM_AUTH_ERR;
        }
        return PAM_SUCCESS;
    }

    /*
     * Otherwise, apply either krb5_aname_to_localname or krb5_kuserok
     * depending on the situation.
     */
    pwd = pam_modutil_getpwnam(args->pamh, ctx->name);
    if (args->ignore_k5login || pwd == NULL) {
        if (krb5_aname_to_localname(c, ctx->princ, sizeof(kuser), kuser) != 0)
            return PAM_AUTH_ERR;
        if (strcmp(kuser, ctx->name) != 0)
            return PAM_AUTH_ERR;
    } else {
        if (!krb5_kuserok(c, ctx->princ, ctx->name))
            return PAM_AUTH_ERR;
    }

    return PAM_SUCCESS;
}