#include "ksu.h"
static void auth_cleanup (FILE *, FILE *, char *);
krb5_boolean fowner(fp, uid)
FILE *fp;
uid_t uid;
{
struct stat sbuf;
if (fstat(fileno(fp), &sbuf)) {
return(FALSE);
}
if ((sbuf.st_uid != uid) && sbuf.st_uid) {
return(FALSE);
}
return(TRUE);
}
krb5_error_code krb5_authorization(context, principal, luser,
cmd, ok, out_fcmd)
krb5_context context;
krb5_principal principal;
const char *luser;
char *cmd;
krb5_boolean *ok;
char **out_fcmd;
{
struct passwd *pwd;
char *princname;
int k5login_flag =0;
int k5users_flag =0;
krb5_boolean retbool =FALSE;
FILE * login_fp = 0, * users_fp = 0;
krb5_error_code retval = 0;
struct stat st_temp;
*ok =FALSE;
if ((pwd = getpwnam(luser)) == NULL)
return 0;
retval = krb5_unparse_name(context, principal, &princname);
if (retval)
return retval;
#ifdef DEBUG
printf("principal to be authorized %s\n", princname);
printf("login file: %s\n", k5login_path);
printf("users file: %s\n", k5users_path);
#endif
k5login_flag = stat(k5login_path, &st_temp);
k5users_flag = stat(k5users_path, &st_temp);
if (!k5login_flag){
if ((login_fp = fopen(k5login_path, "r")) == NULL)
return 0;
if ( fowner(login_fp, pwd->pw_uid) == FALSE) {
fclose(login_fp);
return 0;
}
}
if (!k5users_flag){
if ((users_fp = fopen(k5users_path, "r")) == NULL) {
return 0;
}
if ( fowner(users_fp, pwd->pw_uid) == FALSE){
fclose(users_fp);
return 0;
}
}
if (auth_debug){
fprintf(stderr,
"In krb5_authorization: if auth files exist -> can access\n");
}
#if 0
if (cmd){
if(k5users_flag){
return 0;
}else{
if(retval = k5users_lookup(users_fp,princname,
cmd,&retbool,out_fcmd)){
auth_cleanup(users_fp, login_fp, princname);
return retval;
}else{
*ok =retbool;
return retval;
}
}
}
#endif
if (!k5login_flag){
if (auth_debug)
fprintf(stderr,
"In krb5_authorization: principal to be authorized %s\n",
princname);
retval = k5login_lookup(login_fp, princname, &retbool);
if (retval) {
auth_cleanup(users_fp, login_fp, princname);
return retval;
}
if (retbool) {
if (cmd)
*out_fcmd = xstrdup(cmd);
}
}
if ((!k5users_flag) && (retbool == FALSE) ){
retval = k5users_lookup (users_fp, princname,
cmd, &retbool, out_fcmd);
if(retval) {
auth_cleanup(users_fp, login_fp, princname);
return retval;
}
}
if (k5login_flag && k5users_flag){
char * kuser = (char *) xcalloc (strlen(princname), sizeof(char));
if (!(krb5_aname_to_localname(context, principal,
strlen(princname), kuser))
&& (strcmp(kuser, luser) == 0)) {
retbool = TRUE;
}
free(kuser);
}
*ok =retbool;
auth_cleanup(users_fp, login_fp, princname);
return 0;
}
krb5_error_code k5login_lookup (fp, princname, found)
FILE *fp;
char *princname;
krb5_boolean *found;
{
krb5_error_code retval;
char * line;
char * fprinc;
char * lp;
krb5_boolean loc_found = FALSE;
retval = get_line(fp, &line);
if (retval)
return retval;
while (line){
fprinc = get_first_token (line, &lp);
if (fprinc && (!strcmp(princname, fprinc))){
if( get_next_token (&lp) ){
free (line);
break;
}
else{
loc_found = TRUE;
free (line);
break;
}
}
free (line);
retval = get_line(fp, &line);
if (retval)
return retval;
}
*found = loc_found;
return 0;
}
krb5_error_code k5users_lookup (fp, princname, cmd, found, out_fcmd)
FILE *fp;
char *princname;
char *cmd;
krb5_boolean *found;
char **out_fcmd;
{
krb5_error_code retval;
char * line;
char * fprinc, *fcmd;
char * lp;
char * loc_fcmd = NULL;
krb5_boolean loc_found = FALSE;
retval = get_line(fp, &line);
if (retval)
return retval;
while (line){
fprinc = get_first_token (line, &lp);
if (fprinc && (!strcmp(princname, fprinc))){
fcmd = get_next_token (&lp);
if ((fcmd) && (!strcmp(fcmd, PERMIT_ALL_COMMANDS))){
if (get_next_token(&lp) == NULL){
loc_fcmd =cmd ? xstrdup(cmd): NULL;
loc_found = TRUE;
}
free (line);
break;
}
if (cmd == NULL){
if (fcmd == NULL)
loc_found = TRUE;
free (line);
break;
}else{
if (fcmd != NULL) {
char * temp_rfcmd, *err;
krb5_boolean match;
do {
if(match_commands(fcmd,cmd,&match,
&temp_rfcmd, &err)){
if (auth_debug){
fprintf(stderr,"%s",err);
}
loc_fcmd = err;
break;
}else{
if (match == TRUE){
loc_fcmd = temp_rfcmd;
loc_found = TRUE;
break;
}
}
}while ((fcmd = get_next_token( &lp)));
}
free (line);
break;
}
}
free (line);
retval = get_line(fp, &line);
if (retval) {
return retval;
}
}
*out_fcmd = loc_fcmd;
*found = loc_found;
return 0;
}
krb5_boolean fcmd_resolve(fcmd, out_fcmd, out_err)
char *fcmd;
char ***out_fcmd;
char **out_err;
{
char * err;
char ** tmp_fcmd;
char * path_ptr, *path;
char * lp, * tc;
int i=0;
tmp_fcmd = (char **) xcalloc (MAX_CMD, sizeof(char *));
if (*fcmd == '/'){
tmp_fcmd[0] = xstrdup(fcmd);
tmp_fcmd[1] = NULL;
*out_fcmd = tmp_fcmd;
return TRUE;
}else{
if (strchr(fcmd, '/')){
err = (char *) xcalloc((strlen(fcmd) +200) ,sizeof(char));
sprintf(err,"Error: bad entry - %s in %s file, must be either full path or just the cmd name\n", fcmd, KRB5_USERS_NAME);
*out_err = err;
return FALSE;
}
#ifndef CMD_PATH
err = (char *) xcalloc(2*(strlen(fcmd) +200) ,sizeof(char));
sprintf(err,"Error: bad entry - %s in %s file, since %s is just the cmd name, CMD_PATH must be defined \n", fcmd, KRB5_USERS_NAME, fcmd);
*out_err = err;
return FALSE;
#else
path = xstrdup (CMD_PATH);
path_ptr = path;
while ((*path_ptr == ' ') || (*path_ptr == '\t')) path_ptr ++;
tc = get_first_token (path_ptr, &lp);
if (! tc){
err = (char *) xcalloc((strlen(fcmd) +200) ,sizeof(char));
sprintf(err,"Error: bad entry - %s in %s file, CMD_PATH contains no paths \n", fcmd, KRB5_USERS_NAME);
*out_err = err;
return FALSE;
}
i=0;
do{
if (*tc != '/'){
err = (char *) xcalloc((strlen(tc) +200) ,sizeof(char));
sprintf(err,"Error: bad path %s in CMD_PATH for %s must start with '/' \n",tc, KRB5_USERS_NAME );
*out_err = err;
return FALSE;
}
tmp_fcmd[i] = xasprintf("%s/%s", tc, fcmd);
i++;
} while((tc = get_next_token (&lp)));
tmp_fcmd[i] = NULL;
*out_fcmd = tmp_fcmd;
return TRUE;
#endif
}
}
krb5_boolean cmd_single(cmd)
char * cmd;
{
if ( ( strrchr( cmd, '/')) == NULL){
return TRUE;
}else{
return FALSE;
}
}
int cmd_arr_cmp_postfix(fcmd_arr, cmd)
char **fcmd_arr;
char *cmd;
{
char * temp_fcmd;
char *ptr;
int result =1;
int i = 0;
while(fcmd_arr[i]){
if ( (ptr = strrchr( fcmd_arr[i], '/')) == NULL){
temp_fcmd = fcmd_arr[i];
}else {
temp_fcmd = ptr + 1;
}
result = strcmp (temp_fcmd, cmd);
if (result == 0){
break;
}
i++;
}
return result;
}
int cmd_arr_cmp (fcmd_arr, cmd)
char **fcmd_arr;
char *cmd;
{
int result =1;
int i = 0;
while(fcmd_arr[i]){
result = strcmp (fcmd_arr[i], cmd);
if (result == 0){
break;
}
i++;
}
return result;
}
krb5_boolean find_first_cmd_that_exists(fcmd_arr, cmd_out, err_out)
char **fcmd_arr;
char **cmd_out;
char **err_out;
{
struct stat st_temp;
int i = 0;
krb5_boolean retbool= FALSE;
int j =0;
struct k5buf buf;
while(fcmd_arr[i]){
if (!stat (fcmd_arr[i], &st_temp )){
*cmd_out = xstrdup(fcmd_arr[i]);
retbool = TRUE;
break;
}
i++;
}
if (retbool == FALSE ){
krb5int_buf_init_dynamic(&buf);
krb5int_buf_add(&buf, "Error: not found -> ");
for(j= 0; j < i; j ++)
krb5int_buf_add_fmt(&buf, " %s ", fcmd_arr[j]);
krb5int_buf_add(&buf, "\n");
*err_out = krb5int_buf_data(&buf);
if (*err_out == NULL) {
perror(prog_name);
exit(1);
}
}
return retbool;
}
int match_commands (fcmd, cmd, match, cmd_out, err_out)
char *fcmd;
char *cmd;
krb5_boolean *match;
char **cmd_out;
char **err_out;
{
char ** fcmd_arr;
char * err;
char * cmd_temp;
if(fcmd_resolve(fcmd, &fcmd_arr, &err )== FALSE ){
*err_out = err;
return 1;
}
if (cmd_single( cmd ) == TRUE){
if (!cmd_arr_cmp_postfix(fcmd_arr, cmd)){
if(find_first_cmd_that_exists( fcmd_arr,&cmd_temp,&err)== TRUE){
*match = TRUE;
*cmd_out = cmd_temp;
return 0;
}else{
*err_out = err;
return 1;
}
}else{
*match = FALSE;
return 0;
}
}else{
if (!cmd_arr_cmp(fcmd_arr, cmd)){
*match = TRUE;
*cmd_out = xstrdup(cmd);
return 0;
} else{
*match = FALSE;
return 0;
}
}
}
krb5_error_code get_line (fp, out_line)
FILE *fp;
char **out_line;
{
char * line, *r, *newline , *line_ptr;
int chunk_count = 1;
line = (char *) xcalloc (BUFSIZ, sizeof (char ));
line_ptr = line;
line[0] = '\0';
while (( r = fgets(line_ptr, BUFSIZ , fp)) != NULL){
newline = strchr(line_ptr, '\n');
if (newline) {
*newline = '\0';
break;
}
else {
chunk_count ++;
if(!( line = (char *) realloc( line,
chunk_count * sizeof(char) * BUFSIZ))){
return ENOMEM;
}
line_ptr = line + (BUFSIZ -1) *( chunk_count -1) ;
}
}
if ((r == NULL) && (strlen(line) == 0)) {
*out_line = NULL;
}
else{
*out_line = line;
}
return 0;
}
char * get_first_token (line, lnext)
char *line;
char **lnext;
{
char * lptr, * out_ptr;
out_ptr = line;
lptr = line;
while (( *lptr == ' ') || (*lptr == '\t')) lptr ++;
if (strlen(lptr) == 0) return NULL;
while (( *lptr != ' ') && (*lptr != '\t') && (*lptr != '\0')) lptr ++;
if (*lptr == '\0'){
*lnext = lptr;
} else{
*lptr = '\0';
*lnext = lptr + 1;
}
return out_ptr;
}
char * get_next_token (lnext)
char **lnext;
{
char * lptr, * out_ptr;
lptr = *lnext;
while (( *lptr == ' ') || (*lptr == '\t')) lptr ++;
if (strlen(lptr) == 0) return NULL;
out_ptr = lptr;
while (( *lptr != ' ') && (*lptr != '\t') && (*lptr != '\0')) lptr ++;
if (*lptr == '\0'){
*lnext = lptr;
} else{
*lptr = '\0';
*lnext = lptr + 1;
}
return out_ptr;
}
static void auth_cleanup(users_fp, login_fp, princname)
FILE *users_fp;
FILE *login_fp;
char *princname;
{
free (princname);
if (users_fp)
fclose(users_fp);
if (login_fp)
fclose(login_fp);
}
void init_auth_names(pw_dir)
char *pw_dir;
{
if (strlen (k5login_path) + 2 + strlen (KRB5_LOGIN_NAME) >= MAXPATHLEN) {
fprintf (stderr,
"home directory name `%s' too long, can't search for .k5login\n",
pw_dir);
exit (1);
}
if ((strlen(pw_dir) == 1) && (*pw_dir == '/')){
sprintf(k5login_path,"%s%s", pw_dir, KRB5_LOGIN_NAME);
sprintf(k5users_path,"%s%s", pw_dir, KRB5_USERS_NAME);
} else {
sprintf(k5login_path,"%s/%s", pw_dir, KRB5_LOGIN_NAME);
sprintf(k5users_path,"%s/%s", pw_dir, KRB5_USERS_NAME);
}
}