*/
krb5_error_code krb5_ccache_copy (context, cc_def, cc_other_tag,
- primary_principal, cc_out, stored)
+ primary_principal, cc_out, stored, target_uid)
/* IN */
krb5_context context;
krb5_ccache cc_def;
char *cc_other_tag;
krb5_principal primary_principal;
+uid_t target_uid;
/* OUT */
krb5_ccache *cc_out;
krb5_boolean *stored;
cc_def_name = krb5_cc_get_name(context, cc_def);
cc_other_name = krb5_cc_get_name(context, *cc_other);
+
if ( ! stat(cc_def_name, &st_temp)){
if((retval = krb5_get_nonexp_tkts(context,cc_def,&cc_def_creds_arr))){
return retval;
*stored = krb5_find_princ_in_cred_list(context, cc_def_creds_arr,
primary_principal);
-
+#ifdef HAVE_LSTAT
+ if (!lstat( cc_other_name, &st_temp)) {
+#else /*HAVE_LSTAT*/
+ if (!stat( cc_other_name, &st_temp)) {
+#endif
+ return EINVAL;
+ }
+
+ if (krb5_seteuid(0)||krb5_seteuid(target_uid)) {
+ return errno;
+ }
+
+
if ((retval = krb5_cc_initialize(context, *cc_other, primary_principal))){
return retval;
}
************************************************************************/
krb5_error_code krb5_ccache_copy_restricted (context, cc_def, cc_other_tag,
- prst, cc_out, stored)
+ prst, cc_out, stored, target_uid)
krb5_context context;
krb5_ccache cc_def;
char *cc_other_tag;
krb5_principal prst;
+uid_t target_uid;
/* OUT */
krb5_ccache *cc_out;
krb5_boolean *stored;
}
+#ifdef HAVE_LSTAT
+ if (!lstat( cc_other_name, &st_temp)) {
+#else /*HAVE_LSTAT*/
+ if (!stat( cc_other_name, &st_temp)) {
+#endif
+ return EINVAL;
+ }
+
+ if (krb5_seteuid(0)||krb5_seteuid(target_uid)) {
+ return errno;
+ }
+
+
if ((retval = krb5_cc_initialize(context, *cc_other, prst))){
return retval;
}
cc_source_name = krb5_cc_get_name(context, cc_source);
- /* Reset the euid while we open the source ccache */
-#if defined(_POSIX_SAVED_IDS) && defined(HAVE_SETEUID)
- if (seteuid(source_uid)) {
- com_err(prog_name, errno, "while setting the effective uid");
- exit(1);
- }
-#else
-# if defined(HAVE_SETRESUID)
- if (setresuid(-1, source_uid, -1)) {
- com_err(prog_name, errno, "while setting the effective uid");
- exit(1);
- }
-# else
-# if defined(HAVE_SETREUID)
- if (setreuid(0, source_uid)) {
- com_err(prog_name, errno, "while setting the real/effective uid");
- exit(1);
- }
-# endif /* HAVE_SETREUID */
-# endif /* HAVE_SETRESUID */
-#endif /* _POSIX_SAVED_IDS */
if (! stat(cc_source_name, &st_temp))
if (retval = krb5_cc_get_principal(context, cc_source, &cc_def_princ))
return retval;
-#if defined(_POSIX_SAVED_IDS) && defined(HAVE_SETEUID)
- if (seteuid(0)) {
- com_err(prog_name, errno, "while setting the effective uid");
- exit(1);
- }
-#else
-# if defined(HAVE_SETRESUID)
- if (setresuid(-1, 0, -1)) {
- com_err(prog_name, errno, "while setting the effective uid");
- exit(1);
- }
-# else
-# if defined(HAVE_SETREUID)
- if (setreuid(source_uid, 0)) {
- com_err(prog_name, errno, "while setting the real/effective uid");
- exit(1);
- }
-# endif /* HAVE_SETREUID */
-# endif /* HAVE_SETRESUID */
-#endif /* _POSIX_SAVED_IDS */
if (retval=krb5_parse_name(context, target_user, &target_client))
return retval;
return 0;
}
+ /* Become root, then target for looking at .k5login.*/
+ if (krb5_seteuid(0) || krb5_seteuid(target_uid) ) {
+ return errno;
+ }
+
/* if .k5users and .k5login do not exist */
if (stat(k5login_path, &tb) && stat(k5users_path, &tb) ){
*client = target_client;
/* krb_auth_su.c */
extern krb5_boolean krb5_auth_check
PROTOTYPE((krb5_context, krb5_principal, char *, opt_info *,
- char *, krb5_ccache, int *));
+ char *, krb5_ccache, int *, uid_t));
extern krb5_boolean krb5_fast_auth
PROTOTYPE((krb5_context, krb5_principal, krb5_principal, char *,
/* ccache.c */
extern krb5_error_code krb5_ccache_copy
PROTOTYPE((krb5_context, krb5_ccache, char *, krb5_principal,
- krb5_ccache *, krb5_boolean *));
+ krb5_ccache *, krb5_boolean *, uid_t));
extern krb5_error_code krb5_store_all_creds
PROTOTYPE((krb5_context, krb5_ccache, krb5_creds **, krb5_creds **));
extern krb5_error_code krb5_ccache_copy_restricted
PROTOTYPE((krb5_context, krb5_ccache, char *, krb5_principal,
- krb5_ccache *, krb5_boolean *));
+ krb5_ccache *, krb5_boolean *, uid_t));
extern krb5_error_code krb5_ccache_refresh
PROTOTYPE((krb5_context, krb5_ccache));
#define DEBUG
+/* These are file static so sweep_up can get to them*/
+static uid_t source_uid, target_uid;
+
int
main (argc, argv)
int argc;
krb5_ccache cc_source = NULL;
char * cc_source_tag = NULL;
-uid_t source_uid, target_uid;
uid_t source_gid, target_gid;
char * cc_source_tag_tmp = NULL;
char * cc_target_tag_tmp=NULL;
if (cc_source_tag_tmp == (char *) 1)
cc_source_tag_tmp = cc_source_tag;
}
+ if (krb5_seteuid(source_uid)) {
+ com_err ( prog_name, errno, "while setting euid to source user");
+ exit(1);
+ }
/* get a handle for the cache */
if ((retval = krb5_cc_resolve(ksu_context, cc_source_tag, &cc_source))){
exit(1);
}
+ if (((retval = krb5_cc_set_flags(ksu_context, cc_source, 0x0)) != 0)
+ && (retval != KRB5_FCC_NOFILE)) {
+ com_err(prog_name, retval, "while opening ccache");
+ exit(1);
+ }
+
if ((retval = get_best_princ_for_target(ksu_context, source_uid,
target_uid, source_user, target_user, cc_source,
&options, cmd, localhostname, &client, &hp))){
exit(1);
}
+ /* We may be running as either source or target, depending on
+ what happened; become source.*/
+ if ( geteuid() != source_uid) {
+ if (krb5_seteuid(0) || krb5_seteuid(source_uid) ) {
+ com_err(prog_name, errno, "while returning to source uid after finding best principal");
+ exit(1);
+ }
+ }
+
if (auth_debug){
if (hp){
fprintf(stderr,
"while initializing source cache");
exit(1);
}
- if (chown(cc_source_tag_tmp, source_uid, source_gid)){
- com_err(prog_name, errno,
- "while changing owner for %s",
- cc_source_tag_tmp);
- exit(1);
- }
}
}
if (cc_target_tag == NULL) {
cc_target_tag = (char *)calloc(KRB5_SEC_BUFFSIZE ,sizeof(char));
+ /* make sure that the new ticket file does not already exist
+ This is run as source_uid because it is reasonable to
+ require the source user to have write to where the target
+ cache will be created.*/
+
do {
sprintf(cc_target_tag, "%s%d.%d", KRB5_SECONDARY_CACHE,
target_uid, gen_sym());
cc_target_tag_tmp = strchr(cc_target_tag, ':') + 1;
}while ( !stat ( cc_target_tag_tmp, &st_temp));
- /* make sure that the new ticket file does not already exist */
}
takes place, the target user becomes the owner of the cache.
*/
+ /* we continue to run as source uid until
+ the middle of the copy, when becomewe become the target user
+ The cache is owned by the target user.*/
+
+
if (! use_source_cache){
/* if root ksu's to a regular user, then
if ((source_uid == 0) && (target_uid != 0)) {
if ((retval = krb5_ccache_copy_restricted(ksu_context, cc_source,
- cc_target_tag, client, &cc_target, &stored))){
+ cc_target_tag, client, &cc_target, &stored, target_uid))){
com_err (prog_name, retval,
"while copying cache %s to %s",
krb5_cc_get_name(ksu_context, cc_source),cc_target_tag);
exit(1);
}
- } else{
+ } else{
if ((retval = krb5_ccache_copy(ksu_context, cc_source, cc_target_tag,
- client,&cc_target, &stored))){
+ client,&cc_target, &stored, target_uid))){
com_err (prog_name, retval,
"while copying cache %s to %s",
krb5_cc_get_name(ksu_context, cc_source),
"while searching for client in source ccache");
exit(1);
}
+
+ }
+ /* Become root for authentication*/
+
+ if (krb5_seteuid(0)) {
+ com_err(prog_name, errno, "while reclaiming root uid");
+ exit(1);
}
if ((source_uid == 0) || (target_uid == source_uid)){
char * client_name;
auth_val = krb5_auth_check(ksu_context, client, localhostname, &options,
- target_user,cc_target, &path_passwd);
+ target_user,cc_target, &path_passwd, target_uid);
- /* if kerbereros authentication failed then exit */
+ /* if Kerberos authentication failed then exit */
if (auth_val ==FALSE){
fprintf(stderr, "Authentication failed.\n");
syslog(LOG_WARNING,
exit(1);
}
+#if 0
+ /* At best, this avoids a single kdc request
+ It is hard to implement dealing with file permissions and
+ is unnecessary. It is important
+ to properly handle races in chown if this code is ever re-enabled.
+ */
/* cache the tickets if possible in the source cache */
if (!path_passwd && !use_source_cache){
exit(1);
}
}
-
+#endif /*0*/
+
if ((retval = krb5_unparse_name(ksu_context, client, &client_name))) {
com_err (prog_name, retval, "When unparsing name");
sweep_up(ksu_context, use_source_cache, cc_target);
prog_name,target_user,client_name,
source_user,ontty());
+ /* Run authorization as target.*/
+ if (krb5_seteuid(target_uid)) {
+ com_err(prog_name, errno, "whiel switching to target for authorization check");
+ sweep_up(ksu_context, use_source_cache, cc_target);
+ exit(1);
+ }
+
if ((retval = krb5_authorization(ksu_context, client,target_user,
cmd, &authorization_val, &exec_cmd))){
com_err(prog_name,retval,"while checking authorization");
+krb5_seteuid(0); /*So we have some chance of sweeping up*/
sweep_up(ksu_context, use_source_cache, cc_target);
exit(1);
}
+ if (krb5_seteuid(0)) {
+ com_err(prog_name, errno, "while switching back from target after authorization check");
+ sweep_up(ksu_context, use_source_cache, cc_target);
+ exit(1);
+ }
if (authorization_val == TRUE){
if (cmd) {
if (!use_source_cache){
- /* set up ownership on cache for target user */
-
- if (chown(cc_target_tag_tmp, target_uid, target_gid)){
- com_err(prog_name, errno, "while changing owner for %s",
- cc_target_tag_tmp);
- sweep_up(ksu_context, use_source_cache, cc_target);
- exit(1);
- }
-
}
/* set permissions */
char * cc_name;
struct stat st_temp;
- if (! use_source_cache){
+krb5_seteuid(0);
+krb5_seteuid(target_uid);
+
+if (! use_source_cache){
cc_name = krb5_cc_get_name(context, cc);
if ( ! stat(cc_name, &st_temp)){
if ((retval = krb5_cc_destroy(context, cc))){