]> git.pld-linux.org Git - packages/nfs-utils.git/blob - nfs-utils-heimdal-kcm.patch
- rel 9
[packages/nfs-utils.git] / nfs-utils-heimdal-kcm.patch
1 diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
2 index ccadb07..c1339b6 100644
3 --- a/utils/gssd/gssd.c
4 +++ b/utils/gssd/gssd.c
5 @@ -60,6 +60,7 @@ char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE;
6  char ccachedir[PATH_MAX] = GSSD_DEFAULT_CRED_DIR;
7  char *ccachesearch[GSSD_MAX_CCACHE_SEARCH + 1];
8  int  use_memcache = 0;
9 +int  use_kcmcache = 0;
10  int  root_uses_machine_creds = 1;
11  unsigned int  context_timeout = 0;
12  char *preferred_realm = NULL;
13 @@ -85,7 +86,7 @@ sig_hup(int signal)
14  static void
15  usage(char *progname)
16  {
17 -       fprintf(stderr, "usage: %s [-f] [-M] [-n] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir] [-t timeout] [-R preferred realm]\n",
18 +       fprintf(stderr, "usage: %s [-f] [-K] [-M] [-n] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir] [-t timeout] [-R preferred realm]\n",
19                 progname);
20         exit(1);
21  }
22 @@ -102,7 +103,7 @@ main(int argc, char *argv[])
23         char *progname;
24  
25         memset(ccachesearch, 0, sizeof(ccachesearch));
26 -       while ((opt = getopt(argc, argv, "fvrmnMp:k:d:t:R:")) != -1) {
27 +       while ((opt = getopt(argc, argv, "fvrmnMKp:k:d:t:R:")) != -1) {
28                 switch (opt) {
29                         case 'f':
30                                 fg = 1;
31 @@ -113,6 +114,9 @@ main(int argc, char *argv[])
32                         case 'M':
33                                 use_memcache = 1;
34                                 break;
35 +                       case 'K':
36 +                               use_kcmcache = 1;
37 +                               break;
38                         case 'n':
39                                 root_uses_machine_creds = 0;
40                                 break;
41 diff --git a/utils/gssd/gssd.h b/utils/gssd/gssd.h
42 index b1b5793..82c4406 100644
43 --- a/utils/gssd/gssd.h
44 +++ b/utils/gssd/gssd.h
45 @@ -63,6 +63,7 @@ extern char                   pipefs_dir[PATH_MAX];
46  extern char                    keytabfile[PATH_MAX];
47  extern char                    *ccachesearch[];
48  extern int                     use_memcache;
49 +extern int                     use_kcmcache;
50  extern int                     root_uses_machine_creds;
51  extern unsigned int            context_timeout;
52  extern char                    *preferred_realm;
53 diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
54 index f071600..503cac2 100644
55 --- a/utils/gssd/krb5_util.c
56 +++ b/utils/gssd/krb5_util.c
57 @@ -125,6 +125,7 @@
58  #include "err_util.h"
59  #include "gss_util.h"
60  #include "krb5_util.h"
61 +#include "xcommon.h"
62  
63  /* Global list of principals/cache file names for machine credentials */
64  struct gssd_k5_kt_princ *gssd_k5_kt_princ_list = NULL;
65 @@ -299,6 +300,115 @@ gssd_find_existing_krb5_ccache(uid_t uid, char *dirname, struct dirent **d)
66         return err;
67  }
68  
69 +#ifdef HAVE_HEIMDAL
70 +static int
71 +gssd_find_existing_krb5_ccache_kcm(uid_t uid, char **cc)
72 +{
73 +       krb5_context context;
74 +       krb5_cc_cache_cursor cursor;
75 +       krb5_ccache id;
76 +       char *best_match_name = NULL;
77 +       krb5_timestamp best_match_mtime, mtime;
78 +       char *ccname;
79 +       uid_t ccuid;
80 +       int i;
81 +       int found = 0;
82 +       char buf[1030];
83 +       char *princname = NULL;
84 +       char *realm = NULL;
85 +       int score, best_match_score = 0, err = -EACCES;
86 +
87 +       *cc = NULL;
88 +       if (krb5_init_context(&context))
89 +               return err;
90 +
91 +       if (krb5_cc_cache_get_first(context, "KCM", &cursor))
92 +               return err;
93 +
94 +       while (krb5_cc_cache_next(context, cursor, &id) == 0) {
95 +               ccname = xstrdup(krb5_cc_get_name(context, id));
96 +               if (ccname == NULL) {
97 +                       printerr(0, "Error getting CC name\n");
98 +                       continue;
99 +               }
100 +               for (i=0,ccuid=0; ccname[i] && isdigit(ccname[i]); i++) {
101 +                       ccuid = ccuid*10 + (ccname[i] - '0');
102 +               }
103 +               if (i == 0) {
104 +                       printerr(3, "CC '%s' not available due to"
105 +                                       " non-standard name\n",
106 +                                ccname);
107 +                       continue;
108 +               }
109 +               /* Only pick caches owned by the user (uid) */
110 +               if (ccuid != uid) {
111 +                       printerr(3, "CC '%s' owned by %u, not %u\n",
112 +                                ccname, ccuid, uid);
113 +                       continue;
114 +               }
115 +               snprintf(buf, sizeof(buf), "KCM:%s", ccname);
116 +               if (!query_krb5_ccache(buf, &princname, &realm)) {
117 +                       printerr(3, "CC '%s' is expired or corrupt\n",
118 +                                ccname);
119 +                       err = -EKEYEXPIRED;
120 +                       continue;
121 +               }
122 +               krb5_cc_last_change_time(context, id, &mtime);
123 +
124 +               score = 0;
125 +               if (preferred_realm && strcmp(realm, preferred_realm) == 0) 
126 +                       score++;
127 +
128 +               printerr(3, "CC '%s'(%s@%s) passed all checks and"
129 +                           " has mtime of %u\n",
130 +                        ccname, princname, realm, mtime);
131 +               /*
132 +                * if more than one match is found, return the most
133 +                * recent (the one with the latest mtime), and
134 +                * don't free the dirent
135 +                */
136 +               if (!found) {
137 +                       best_match_name = ccname;
138 +                       best_match_mtime = mtime;
139 +                       best_match_score = score;
140 +                       found++;
141 +               } else {
142 +                       /*
143 +                        * If current score is higher than best match 
144 +                        * score, we use the current match. Otherwise,
145 +                        * if the current match has an mtime later
146 +                        * than the one we are looking at, then use
147 +                        * the current match.  Otherwise, we still
148 +                        * have the best match.
149 +                        */
150 +                       if (best_match_score < score ||
151 +                           (best_match_score == score && 
152 +                              mtime > best_match_mtime)) {
153 +                               free(best_match_name);
154 +                               best_match_name = ccname;
155 +                               best_match_mtime = mtime;
156 +                               best_match_score = score;
157 +                       } else {
158 +                               free(ccname);
159 +                       }
160 +                       printerr(3, "CC '%s' is our current best match "
161 +                                   "with mtime of %u\n",
162 +                                best_match_name, best_match_mtime);
163 +               }
164 +               free(princname);
165 +               free(realm);
166 +       }
167 +       krb5_cc_cache_end_seq_get(context, cursor);
168 +       krb5_free_context(context);
169 +       if (found) {
170 +               *cc = best_match_name;
171 +               return 0;
172 +       }
173 +
174 +       return err;
175 +}
176 +#endif
177 +
178  /*
179   * Obtain credentials via a key in the keytab given
180   * a keytab handle and a gssd_k5_kt_princ structure.
181 @@ -1002,12 +1112,26 @@ gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername, char *dirname)
182         printerr(2, "getting credentials for client with uid %u for "
183                     "server %s\n", uid, servername);
184         memset(buf, 0, sizeof(buf));
185 -       err = gssd_find_existing_krb5_ccache(uid, dirname, &d);
186 -       if (err)
187 -               return err;
188 +#ifdef HAVE_HEIMDAL
189 +       if (use_kcmcache) {
190 +               char *s;
191 +               err = gssd_find_existing_krb5_ccache_kcm(uid, &s);
192 +               if (err)
193 +                       return err;
194 +
195 +               snprintf(buf, sizeof(buf), "KCM:%s", s);
196 +               free(s);
197 +       } else {
198 +#endif
199 +               err = gssd_find_existing_krb5_ccache(uid, dirname, &d);
200 +               if (err)
201 +                       return err;
202  
203 -       snprintf(buf, sizeof(buf), "FILE:%s/%s", dirname, d->d_name);
204 -       free(d);
205 +               snprintf(buf, sizeof(buf), "FILE:%s/%s", dirname, d->d_name);
206 +               free(d);
207 +#ifdef HAVE_HEIMDAL
208 +       }
209 +#endif
210  
211         printerr(2, "using %s as credentials cache for client with "
212                     "uid %u for server %s\n", buf, uid, servername);
This page took 0.074895 seconds and 3 git commands to generate.