@@ -39,15 +39,108 @@ void gp_free_creds_handle(struct gp_creds_handle **in)
3939 return ;
4040}
4141
42+ uint32_t gp_init_creds_with_keytab (uint32_t * min , const char * svc_name ,
43+ const char * keytab ,
44+ struct gp_creds_handle * handle )
45+ {
46+ char ktname [MAX_KEYTAB_NAME_LEN + 1 ] = {0 };
47+ krb5_keytab ktid = NULL ;
48+ krb5_kt_cursor cursor ;
49+ krb5_keytab_entry entry ;
50+ krb5_enctype * permitted ;
51+ uint32_t ret_maj = 0 ;
52+ uint32_t ret_min = 0 ;
53+ int ret ;
54+
55+ if (keytab ) {
56+ strncpy (ktname , keytab , MAX_KEYTAB_NAME_LEN );
57+ ret = krb5_kt_resolve (handle -> context , keytab , & ktid );
58+ }
59+ /* if the keytab is not specified or fails to resolve try default */
60+ if (!keytab || ret != 0 ) {
61+ ret = krb5_kt_default_name (handle -> context , ktname ,
62+ MAX_KEYTAB_NAME_LEN );
63+ if (ret ) {
64+ strncpy (ktname , "[default]" , MAX_KEYTAB_NAME_LEN );
65+ }
66+ ret = krb5_kt_default (handle -> context , & ktid );
67+ }
68+ if (ret == 0 ) {
69+ ret = krb5_kt_have_content (handle -> context , ktid );
70+ }
71+ if (ret ) {
72+ GPDEBUG ("Keytab %s has no content (%d)\n" , ktname , ret );
73+ ret_min = ret ;
74+ ret_maj = GSS_S_CRED_UNAVAIL ;
75+ goto done ;
76+ }
77+
78+ ret = krb5_get_permitted_enctypes (handle -> context , & permitted );
79+ if (ret ) {
80+ GPDEBUG ("Failed to source permitted enctypes (%d)\n" , ret );
81+ ret_min = ret ;
82+ ret_maj = GSS_S_FAILURE ;
83+ goto done ;
84+ }
85+
86+ ret = krb5_kt_start_seq_get (handle -> context , ktid , & cursor );
87+ if (ret ) {
88+ GPDEBUG ("krb5_kt_start_seq_get() failed (%d)\n" , ret );
89+ ret_min = ret ;
90+ ret_maj = GSS_S_FAILURE ;
91+ goto done ;
92+ }
93+ do {
94+ ret = krb5_kt_next_entry (handle -> context , ktid , & entry , & cursor );
95+ if (ret == 0 ) {
96+ for (unsigned i = 0 ; permitted [i ] != 0 ; i ++ ) {
97+ if (permitted [i ] == entry .key .enctype ) {
98+ /* should we derive a key instead ? */
99+ ret = krb5_copy_keyblock (handle -> context , & entry .key ,
100+ & handle -> key );
101+ if (ret == 0 ) {
102+ GPDEBUG ("Service: %s, Keytab: %s, Enctype: %d\n" ,
103+ svc_name , ktname , entry .key .enctype );
104+ ret = KRB5_KT_END ;
105+ } else {
106+ GPDEBUG ("krb5_copy_keyblock failed (%d)\n" , ret );
107+ }
108+ break ;
109+ }
110+ }
111+ (void )krb5_free_keytab_entry_contents (handle -> context , & entry );
112+ }
113+ } while (ret == 0 );
114+ (void )krb5_kt_end_seq_get (handle -> context , ktid , & cursor );
115+ if ((ret == KRB5_KT_END ) && (handle -> key == NULL )) {
116+ ret = KRB5_WRONG_ETYPE ;
117+ ret_maj = GSS_S_CRED_UNAVAIL ;
118+ goto done ;
119+ }
120+ if (ret != KRB5_KT_END ) {
121+ ret_min = ret ;
122+ ret_maj = GSS_S_CRED_UNAVAIL ;
123+ goto done ;
124+ }
125+
126+ ret_min = 0 ;
127+ ret_maj = GSS_S_COMPLETE ;
128+
129+ done :
130+ if (ktid ) {
131+ (void )krb5_kt_close (handle -> context , ktid );
132+ }
133+ * min = ret_min ;
134+ return ret_maj ;
135+ }
136+
42137uint32_t gp_init_creds_handle (uint32_t * min , const char * svc_name ,
43138 const char * keytab ,
44139 struct gp_creds_handle * * out )
45140{
46141 struct gp_creds_handle * handle ;
47142 uint32_t ret_maj = 0 ;
48143 uint32_t ret_min = 0 ;
49- krb5_keytab ktid = NULL ;
50- char ktname [MAX_KEYTAB_NAME_LEN + 1 ] = {0 };
51144 int ret ;
52145
53146 handle = calloc (1 , sizeof (struct gp_creds_handle ));
@@ -67,85 +160,9 @@ uint32_t gp_init_creds_handle(uint32_t *min, const char *svc_name,
67160
68161 /* Try to use a keytab, and fall back to a random runtime secret if all
69162 * else fails */
70- if (keytab ) {
71- ret = krb5_kt_resolve (handle -> context , keytab , & ktid );
72- if (ret == 0 ) {
73- ret = krb5_kt_have_content (handle -> context , ktid );
74- }
75- /* if a keytab is specified then it must be usable */
76- if (ret ) {
77- ret_min = ret ;
78- ret_maj = GSS_S_CRED_UNAVAIL ;
79- goto done ;
80- }
81- strncpy (ktname , keytab , MAX_KEYTAB_NAME_LEN );
82- } else {
83- ret = krb5_kt_default (handle -> context , & ktid );
84- /* if the default keyab does not exist or is empty it is not fatal */
85- if (ret ) {
86- ktid = NULL ;
87- } else {
88- ret = krb5_kt_have_content (handle -> context , ktid );
89- if (ret ) {
90- (void )krb5_kt_close (handle -> context , ktid );
91- ktid = NULL ;
92- } else {
93- ret = krb5_kt_default_name (handle -> context , ktname ,
94- MAX_KEYTAB_NAME_LEN );
95- if (ret ) strncpy (ktname , "[default]" , MAX_KEYTAB_NAME_LEN );
96- }
97- }
98- }
99-
100- if (ktid ) {
101- krb5_kt_cursor cursor ;
102- krb5_keytab_entry entry ;
103- krb5_enctype * permitted ;
104-
105- ret = krb5_get_permitted_enctypes (handle -> context , & permitted );
106- if (ret ) {
107- ret_min = ret ;
108- ret_maj = GSS_S_FAILURE ;
109- goto done ;
110- }
111-
112- ret = krb5_kt_start_seq_get (handle -> context , ktid , & cursor );
113- if (ret ) {
114- ret_min = ret ;
115- ret_maj = GSS_S_FAILURE ;
116- goto done ;
117- }
118- do {
119- ret = krb5_kt_next_entry (handle -> context , ktid , & entry , & cursor );
120- if (ret == 0 ) {
121- for (unsigned i = 0 ; permitted [i ] != 0 ; i ++ ) {
122- if (permitted [i ] == entry .key .enctype ) {
123- /* should we derive a key instead ? */
124- ret = krb5_copy_keyblock (handle -> context , & entry .key ,
125- & handle -> key );
126- if (ret == 0 ) {
127- GPDEBUG ("Service: %s, Enckey: %s, Enctype: %d\n" ,
128- svc_name , ktname , entry .key .enctype );
129- ret = KRB5_KT_END ;
130- }
131- break ;
132- }
133- }
134- (void )krb5_free_keytab_entry_contents (handle -> context , & entry );
135- }
136- } while (ret == 0 );
137- (void )krb5_kt_end_seq_get (handle -> context , ktid , & cursor );
138- if ((ret == KRB5_KT_END ) && (handle -> key == NULL )) {
139- ret = KRB5_WRONG_ETYPE ;
140- ret_maj = GSS_S_CRED_UNAVAIL ;
141- goto done ;
142- }
143- if (ret != KRB5_KT_END ) {
144- ret_min = ret ;
145- ret_maj = GSS_S_CRED_UNAVAIL ;
146- goto done ;
147- }
148- } else {
163+ ret_maj = gp_init_creds_with_keytab (& ret_min , svc_name , keytab , handle );
164+ if (ret_maj != GSS_S_COMPLETE ) {
165+ /* fallback */
149166 ret = krb5_init_keyblock (handle -> context ,
150167 GP_CREDS_HANDLE_KEY_ENCTYPE , 0 ,
151168 & handle -> key );
@@ -167,9 +184,6 @@ uint32_t gp_init_creds_handle(uint32_t *min, const char *svc_name,
167184 ret_min = 0 ;
168185
169186done :
170- if (handle -> context && ktid ) {
171- (void )krb5_kt_close (handle -> context , ktid );
172- }
173187 * min = ret_min ;
174188 if (ret_maj ) {
175189 gp_free_creds_handle (& handle );
0 commit comments