Services4User review
Greg Hudson
ghudson at MIT.EDU
Mon Aug 24 16:49:51 EDT 2009
I have made a first pass over about half of the changes on your user
branch. I will need to do a more comprehensive second pass after doing
some more background reading (I read the Microsoft S4U specification,
but there are limitations to my GSSAPI understanding, and I also simply
need to block out more time). But since you're going to be doing a
bunch of ongoing krb5 work, I want to bring up some coding practices
issues. Some of this is nitpicky.
* Do not make lines overflowing 79 columns if possible. Examples:
- kdc_util.c line 923
- kdc_process_s4u2self_rep (multiple cases)
- kdc_process_s4u2self_req (multiple cases)
- process_tgs_req
- do_tgs_req.c line 701
- kvno.c line 42 (text output also overflows; previously bad)
- kvno.c line 94 (can use ANSI C string concatenation)
- kvno.c line 283 (previously bad)
- kvno.c line 288, 303
- t_s4u.c line 53
- s4u_gss_glue.c line 134, 292
- g_acquire_cred_imp_cred.c line 190, 191
* Do not put parens around return expressions:
- g_acquire_cred_imp_cred.c
- g_acquire_cred_imp_name.c
(These may be the result of copying existing code.)
* Code documentation was good in many places, but I noted some holes:
- verify_s4u_x509_user_checksum should explain why it's trying two
ways.
- kdc_process_s4u2self_rep is a bad name. "kdc_process_*" was
previously used only for examining request data, and is a bad name
prefix even then. In this case you are composing reply data. Also,
this function should have a leading comment explaining what it does,
unless you can come up with a name and parameter names which are super
self-explanatory.
- krb5int_send_tgs grew a new callback parameter; its meaning should
be documented in a comment before the function definition in send_tgs.c
Part of the issue here is that we do not commonly document internal
function contracts, and would like to change that. It's a huge job to
fix this for all of our existing code, but we should at least document
new functions we add when they're not trivially obvious.
* Do not cast the return value of malloc; examples:
- kdc_process_s4u2self_rep
- kdc_process_s4u2self_req
- add_pa_data_element
- kg_compose_deleg_cred
- g_acquire_cred_imp_cred.c
- gss_acquire_cred_impersonate_name
- gss_add_cred_impersonate_name
* Do not void-cast return values which are almost always ignored. (This
is specified in the coding practices document on the wiki, but is I
believe the general practice in krb5 code, and is also a good
readability practice in my opinion.) I didn't collect examples here,
but I saw void casts for memset, memcpy, and the gss_release functions.
For the purposes of static analysis, I think Coverity has a good
approach here: it will only complain about the lack of a void cast when
it can statistically determine that the return value is usually used.
* Do not add space between sizeof and the following open paren. I
didn't collect examples here.
* Do not check for nullity before calling free or krb5_free functions.
(I don't think this is in the coding practices document but is what
we're moving towards.) Examples:
- kdc_process_s4u2self_rep cleanup
- (do_tgs_req.c line 988 but mixed in with others)
- do_v5_kvno cleanup
- init_sec_context.c:get_credentials cleanup
- kg_compose_deleg_cred cleanup
- gss_add_cred_impersonate_cred cleanup
- gss_add_cred_impersonate_name cleanup
* In kdc_process_s4u2self_req:
- Use a cleanup handler, not "free everything and exit" flow control
- Initialize *s4u_x509_user to NULL at start, use a temporary during
construction, and ssign the temporary to the output value just
before returning success
* Trailing blank lines added to some files; examples:
- kdc_preauth.c
- krb5_gss_glue.c
- acquire_cred.c
* Unrelated #if 0s added to ksetpwd.c.
* We are trying to avoid large functions which are hard to see on a
screenful of text or understand within your head. This means if you're
writing a large function, or adding to a moderately-sized or large
function, you should look for opportunities to naturally break things up
into helper functions. Some places where I noted opportunities for this
include:
- kdc_process_s4u2self_req, pa_type == KRB5_PADATA_S4U_X509_USER
conditional block
- kdc_process_s4u2self_req, is_local_principal conditional block
- init_sec_context.c:get_credentials, new proxy_cred conditional
* In krb5_gss_cred_id_rec you introduce some bitfields where none were
present. I don't know if it is important to contain the size of id_rec
structures, and using bitfields can expand the size of the code which
processes those fields, which at times can be more undesirable than
allocating a bit more memory in an infrequently-used structure. I am
not sure how the balance comes out in this case, but please be aware of
the tradeoff.
More information about the krbdev
mailing list