diff options
Diffstat (limited to 'crypto/krb5/doc/appdev/init_creds.rst')
-rw-r--r-- | crypto/krb5/doc/appdev/init_creds.rst | 304 |
1 files changed, 0 insertions, 304 deletions
diff --git a/crypto/krb5/doc/appdev/init_creds.rst b/crypto/krb5/doc/appdev/init_creds.rst deleted file mode 100644 index 5c3c0a87c5da..000000000000 --- a/crypto/krb5/doc/appdev/init_creds.rst +++ /dev/null @@ -1,304 +0,0 @@ -Initial credentials -=================== - -Software that performs tasks such as logging users into a computer -when they type their Kerberos password needs to get initial -credentials (usually ticket granting tickets) from Kerberos. Such -software shares some behavior with the :ref:`kinit(1)` program. - -Whenever a program grants access to a resource (such as a local login -session on a desktop computer) based on a user successfully getting -initial Kerberos credentials, it must verify those credentials against -a secure shared secret (e.g., a host keytab) to ensure that the user -credentials actually originate from a legitimate KDC. Failure to -perform this verification is a critical vulnerability, because a -malicious user can execute the "Zanarotti attack": the user constructs -a fake response that appears to come from the legitimate KDC, but -whose contents come from an attacker-controlled KDC. - -Some applications read a Kerberos password over the network (ideally -over a secure channel), which they then verify against the KDC. While -this technique may be the only practical way to integrate Kerberos -into some existing legacy systems, its use is contrary to the original -design goals of Kerberos. - -The function :c:func:`krb5_get_init_creds_password` will get initial -credentials for a client using a password. An application that needs -to verify the credentials can call :c:func:`krb5_verify_init_creds`. -Here is an example of code to obtain and verify TGT credentials, given -strings *princname* and *password* for the client principal name and -password:: - - krb5_error_code ret; - krb5_creds creds; - krb5_principal client_princ = NULL; - - memset(&creds, 0, sizeof(creds)); - ret = krb5_parse_name(context, princname, &client_princ); - if (ret) - goto cleanup; - ret = krb5_get_init_creds_password(context, &creds, client_princ, - password, NULL, NULL, 0, NULL, NULL); - if (ret) - goto cleanup; - ret = krb5_verify_init_creds(context, &creds, NULL, NULL, NULL, NULL); - - cleanup: - krb5_free_principal(context, client_princ); - krb5_free_cred_contents(context, &creds); - return ret; - -Options for get_init_creds --------------------------- - -The function :c:func:`krb5_get_init_creds_password` takes an options -parameter (which can be a null pointer). Use the function -:c:func:`krb5_get_init_creds_opt_alloc` to allocate an options -structure, and :c:func:`krb5_get_init_creds_opt_free` to free it. For -example:: - - krb5_error_code ret; - krb5_get_init_creds_opt *opt = NULL; - krb5_creds creds; - - memset(&creds, 0, sizeof(creds)); - ret = krb5_get_init_creds_opt_alloc(context, &opt); - if (ret) - goto cleanup; - krb5_get_init_creds_opt_set_tkt_life(opt, 24 * 60 * 60); - ret = krb5_get_init_creds_password(context, &creds, client_princ, - password, NULL, NULL, 0, NULL, opt); - if (ret) - goto cleanup; - - cleanup: - krb5_get_init_creds_opt_free(context, opt); - krb5_free_cred_contents(context, &creds); - return ret; - -Getting anonymous credentials ------------------------------ - -As of release 1.8, it is possible to obtain fully anonymous or -partially anonymous (realm-exposed) credentials, if the KDC supports -it. The MIT KDC supports issuing fully anonymous credentials as of -release 1.8 if configured appropriately (see :ref:`anonymous_pkinit`), -but does not support issuing realm-exposed anonymous credentials at -this time. - -To obtain fully anonymous credentials, call -:c:func:`krb5_get_init_creds_opt_set_anonymous` on the options -structure to set the anonymous flag, and specify a client principal -with the KDC's realm and a single empty data component (the principal -obtained by parsing ``@``\ *realmname*). Authentication will take -place using anonymous PKINIT; if successful, the client principal of -the resulting tickets will be -``WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS``. Here is an example:: - - krb5_get_init_creds_opt_set_anonymous(opt, 1); - ret = krb5_build_principal(context, &client_princ, strlen(myrealm), - myrealm, "", (char *)NULL); - if (ret) - goto cleanup; - ret = krb5_get_init_creds_password(context, &creds, client_princ, - password, NULL, NULL, 0, NULL, opt); - if (ret) - goto cleanup; - -To obtain realm-exposed anonymous credentials, set the anonymous flag -on the options structure as above, but specify a normal client -principal in order to prove membership in the realm. Authentication -will take place as it normally does; if successful, the client -principal of the resulting tickets will be ``WELLKNOWN/ANONYMOUS@``\ -*realmname*. - -User interaction ----------------- - -Authenticating a user usually requires the entry of secret -information, such as a password. A password can be supplied directly -to :c:func:`krb5_get_init_creds_password` via the *password* -parameter, or the application can supply prompter and/or responder -callbacks instead. If callbacks are used, the user can also be -queried for other secret information such as a PIN, informed of -impending password expiration, or prompted to change a password which -has expired. - -Prompter callback -~~~~~~~~~~~~~~~~~ - -A prompter callback can be specified via the *prompter* and *data* -parameters to :c:func:`krb5_get_init_creds_password`. The prompter -will be invoked each time the krb5 library has a question to ask or -information to present. When the prompter callback is invoked, the -*banner* argument (if not null) is intended to be displayed to the -user, and the questions to be answered are specified in the *prompts* -array. Each prompt contains a text question in the *prompt* field, a -*hidden* bit to indicate whether the answer should be hidden from -display, and a storage area for the answer in the *reply* field. The -callback should fill in each question's ``reply->data`` with the -answer, up to a maximum number of ``reply->length`` bytes, and then -reset ``reply->length`` to the length of the answer. - -A prompter callback can call :c:func:`krb5_get_prompt_types` to get an -array of type constants corresponding to the prompts, to get -programmatic information about the semantic meaning of the questions. -:c:func:`krb5_get_prompt_types` may return a null pointer if no prompt -type information is available. - -Text-based applications can use a built-in text prompter -implementation by supplying :c:func:`krb5_prompter_posix` as the -*prompter* parameter and a null pointer as the *data* parameter. For -example:: - - ret = krb5_get_init_creds_password(context, &creds, client_princ, - NULL, krb5_prompter_posix, NULL, 0, - NULL, NULL); - -Responder callback -~~~~~~~~~~~~~~~~~~ - -A responder callback can be specified through the init_creds options -using the :c:func:`krb5_get_init_creds_opt_set_responder` function. -Responder callbacks can present a more sophisticated user interface -for authentication secrets. The responder callback is usually invoked -only once per authentication, with a list of questions produced by all -of the allowed preauthentication mechanisms. - -When the responder callback is invoked, the *rctx* argument can be -accessed to obtain the list of questions and to answer them. The -:c:func:`krb5_responder_list_questions` function retrieves an array of -question types. For each question type, the -:c:func:`krb5_responder_get_challenge` function retrieves additional -information about the question, if applicable, and the -:c:func:`krb5_responder_set_answer` function sets the answer. - -Responder question types, challenges, and answers are UTF-8 strings. -The question type is a well-known string; the meaning of the challenge -and answer depend on the question type. If an application does not -understand a question type, it cannot interpret the challenge or -provide an answer. Failing to answer a question typically results in -the prompter callback being used as a fallback. - -Password question -################# - -The :c:macro:`KRB5_RESPONDER_QUESTION_PASSWORD` (or ``"password"``) -question type requests the user's password. This question does not -have a challenge, and the response is simply the password string. - -One-time password question -########################## - -The :c:macro:`KRB5_RESPONDER_QUESTION_OTP` (or ``"otp"``) question -type requests a choice among one-time password tokens and the PIN and -value for the chosen token. The challenge and answer are JSON-encoded -strings, but an application can use convenience functions to avoid -doing any JSON processing itself. - -The :c:func:`krb5_responder_otp_get_challenge` function decodes the -challenge into a krb5_responder_otp_challenge structure. The -:c:func:`krb5_responder_otp_set_answer` function selects one of the -token information elements from the challenge and supplies the value -and pin for that token. - -PKINIT password or PIN question -############################### - -The :c:macro:`KRB5_RESPONDER_QUESTION_PKINIT` (or ``"pkinit"``) question -type requests PINs for hardware devices and/or passwords for encrypted -credentials which are stored on disk, potentially also supplying -information about the state of the hardware devices. The challenge and -answer are JSON-encoded strings, but an application can use convenience -functions to avoid doing any JSON processing itself. - -The :c:func:`krb5_responder_pkinit_get_challenge` function decodes the -challenges into a krb5_responder_pkinit_challenge structure. The -:c:func:`krb5_responder_pkinit_set_answer` function can be used to -supply the PIN or password for a particular client credential, and can -be called multiple times. - -Example -####### - -Here is an example of using a responder callback:: - - static krb5_error_code - my_responder(krb5_context context, void *data, - krb5_responder_context rctx) - { - krb5_error_code ret; - krb5_responder_otp_challenge *chl; - - if (krb5_responder_get_challenge(context, rctx, - KRB5_RESPONDER_QUESTION_PASSWORD)) { - ret = krb5_responder_set_answer(context, rctx, - KRB5_RESPONDER_QUESTION_PASSWORD, - "open sesame"); - if (ret) - return ret; - } - ret = krb5_responder_otp_get_challenge(context, rctx, &chl); - if (ret == 0 && chl != NULL) { - ret = krb5_responder_otp_set_answer(context, rctx, 0, "1234", - NULL); - krb5_responder_otp_challenge_free(context, rctx, chl); - if (ret) - return ret; - } - return 0; - } - - static krb5_error_code - get_creds(krb5_context context, krb5_principal client_princ) - { - krb5_error_code ret; - krb5_get_init_creds_opt *opt = NULL; - krb5_creds creds; - - memset(&creds, 0, sizeof(creds)); - ret = krb5_get_init_creds_opt_alloc(context, &opt); - if (ret) - goto cleanup; - ret = krb5_get_init_creds_opt_set_responder(context, opt, my_responder, - NULL); - if (ret) - goto cleanup; - ret = krb5_get_init_creds_password(context, &creds, client_princ, - NULL, NULL, NULL, 0, NULL, opt); - - cleanup: - krb5_get_init_creds_opt_free(context, opt); - krb5_free_cred_contents(context, &creds); - return ret; - } - -Verifying initial credentials ------------------------------ - -Use the function :c:func:`krb5_verify_init_creds` to verify initial -credentials. It takes an options structure (which can be a null -pointer). Use :c:func:`krb5_verify_init_creds_opt_init` to initialize -the caller-allocated options structure, and -:c:func:`krb5_verify_init_creds_opt_set_ap_req_nofail` to set the -"nofail" option. For example:: - - krb5_verify_init_creds_opt vopt; - - krb5_verify_init_creds_opt_init(&vopt); - krb5_verify_init_creds_opt_set_ap_req_nofail(&vopt, 1); - ret = krb5_verify_init_creds(context, &creds, NULL, NULL, NULL, &vopt); - -The confusingly named "nofail" option, when set, means that the -verification must actually succeed in order for -:c:func:`krb5_verify_init_creds` to indicate success. The default -state of this option (cleared) means that if there is no key material -available to verify the user credentials, the verification will -succeed anyway. (The default can be changed by a configuration file -setting.) - -This accommodates a use case where a large number of unkeyed shared -desktop workstations need to allow users to log in using Kerberos. -The security risks from this practice are mitigated by the absence of -valuable state on the shared workstations---any valuable resources -that the users would access reside on networked servers. |