1c19800e8SDoug Rabson /* 2*ae771770SStanislav Sedov * Copyright (c) 2007-2008 Kungliga Tekniska Högskolan 3c19800e8SDoug Rabson * (Royal Institute of Technology, Stockholm, Sweden). 4c19800e8SDoug Rabson * All rights reserved. 5c19800e8SDoug Rabson * 6c19800e8SDoug Rabson * Redistribution and use in source and binary forms, with or without 7c19800e8SDoug Rabson * modification, are permitted provided that the following conditions 8c19800e8SDoug Rabson * are met: 9c19800e8SDoug Rabson * 10c19800e8SDoug Rabson * 1. Redistributions of source code must retain the above copyright 11c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer. 12c19800e8SDoug Rabson * 13c19800e8SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 14c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer in the 15c19800e8SDoug Rabson * documentation and/or other materials provided with the distribution. 16c19800e8SDoug Rabson * 17c19800e8SDoug Rabson * 3. Neither the name of the Institute nor the names of its contributors 18c19800e8SDoug Rabson * may be used to endorse or promote products derived from this software 19c19800e8SDoug Rabson * without specific prior written permission. 20c19800e8SDoug Rabson * 21c19800e8SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22c19800e8SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23c19800e8SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24c19800e8SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25c19800e8SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26c19800e8SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27c19800e8SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28c19800e8SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29c19800e8SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30c19800e8SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31c19800e8SDoug Rabson * SUCH DAMAGE. 32c19800e8SDoug Rabson */ 33c19800e8SDoug Rabson 34c19800e8SDoug Rabson #include "krb5_locl.h" 35c19800e8SDoug Rabson 36c19800e8SDoug Rabson /** 37c19800e8SDoug Rabson * 38c19800e8SDoug Rabson */ 39c19800e8SDoug Rabson 40*ae771770SStanislav Sedov /*! @mainpage Heimdal Kerberos 5 library 41c19800e8SDoug Rabson * 42*ae771770SStanislav Sedov * @section intro Introduction 43c19800e8SDoug Rabson * 44c19800e8SDoug Rabson * Heimdal libkrb5 library is a implementation of the Kerberos 45c19800e8SDoug Rabson * protocol. 46c19800e8SDoug Rabson * 47c19800e8SDoug Rabson * Kerberos is a system for authenticating users and services on a 48c19800e8SDoug Rabson * network. It is built upon the assumption that the network is 49c19800e8SDoug Rabson * ``unsafe''. For example, data sent over the network can be 50c19800e8SDoug Rabson * eavesdropped and altered, and addresses can also be faked. 51c19800e8SDoug Rabson * Therefore they cannot be used for authentication purposes. 52c19800e8SDoug Rabson * 53*ae771770SStanislav Sedov * 54*ae771770SStanislav Sedov * - @ref krb5_introduction 55*ae771770SStanislav Sedov * - @ref krb5_principal_intro 56*ae771770SStanislav Sedov * - @ref krb5_ccache_intro 57*ae771770SStanislav Sedov * - @ref krb5_keytab_intro 58*ae771770SStanislav Sedov * 59*ae771770SStanislav Sedov * If you want to know more about the file formats that is used by 60*ae771770SStanislav Sedov * Heimdal, please see: @ref krb5_fileformats 61*ae771770SStanislav Sedov * 62*ae771770SStanislav Sedov * The project web page: http://www.h5l.org/ 63c19800e8SDoug Rabson * 64c19800e8SDoug Rabson */ 65c19800e8SDoug Rabson 66c19800e8SDoug Rabson /** @defgroup krb5 Heimdal Kerberos 5 library */ 67c19800e8SDoug Rabson /** @defgroup krb5_address Heimdal Kerberos 5 address functions */ 68*ae771770SStanislav Sedov /** @defgroup krb5_principal Heimdal Kerberos 5 principal functions */ 69c19800e8SDoug Rabson /** @defgroup krb5_ccache Heimdal Kerberos 5 credential cache functions */ 70*ae771770SStanislav Sedov /** @defgroup krb5_crypto Heimdal Kerberos 5 cryptography functions */ 71c19800e8SDoug Rabson /** @defgroup krb5_credential Heimdal Kerberos 5 credential handing functions */ 72c19800e8SDoug Rabson /** @defgroup krb5_deprecated Heimdal Kerberos 5 deprecated functions */ 73c19800e8SDoug Rabson /** @defgroup krb5_digest Heimdal Kerberos 5 digest service */ 74c19800e8SDoug Rabson /** @defgroup krb5_error Heimdal Kerberos 5 error reporting functions */ 75*ae771770SStanislav Sedov /** @defgroup krb5_keytab Heimdal Kerberos 5 keytab handling functions */ 76*ae771770SStanislav Sedov /** @defgroup krb5_ticket Heimdal Kerberos 5 ticket functions */ 77*ae771770SStanislav Sedov /** @defgroup krb5_pac Heimdal Kerberos 5 PAC handling functions */ 78c19800e8SDoug Rabson /** @defgroup krb5_v4compat Heimdal Kerberos 4 compatiblity functions */ 79*ae771770SStanislav Sedov /** @defgroup krb5_storage Heimdal Kerberos 5 storage functions */ 80c19800e8SDoug Rabson /** @defgroup krb5_support Heimdal Kerberos 5 support functions */ 81*ae771770SStanislav Sedov /** @defgroup krb5_auth Heimdal Kerberos 5 authentication functions */ 82*ae771770SStanislav Sedov 83*ae771770SStanislav Sedov 84*ae771770SStanislav Sedov /** 85*ae771770SStanislav Sedov * @page krb5_introduction Introduction to the Kerberos 5 API 86*ae771770SStanislav Sedov * @section api_overview Kerberos 5 API Overview 87*ae771770SStanislav Sedov * 88*ae771770SStanislav Sedov * All functions are documented in manual pages. This section tries 89*ae771770SStanislav Sedov * to give an overview of the major components used in Kerberos 90*ae771770SStanislav Sedov * library, and point to where to look for a specific function. 91*ae771770SStanislav Sedov * 92*ae771770SStanislav Sedov * @subsection intro_krb5_context Kerberos context 93*ae771770SStanislav Sedov * 94*ae771770SStanislav Sedov * A kerberos context (krb5_context) holds all per thread state. All 95*ae771770SStanislav Sedov * global variables that are context specific are stored in this 96*ae771770SStanislav Sedov * structure, including default encryption types, credential cache 97*ae771770SStanislav Sedov * (for example, a ticket file), and default realms. 98*ae771770SStanislav Sedov * 99*ae771770SStanislav Sedov * The internals of the structure should never be accessed directly, 100*ae771770SStanislav Sedov * functions exist for extracting information. 101*ae771770SStanislav Sedov * 102*ae771770SStanislav Sedov * See the manual page for krb5_init_context() how to create a context 103*ae771770SStanislav Sedov * and module @ref krb5 for more information about the functions. 104*ae771770SStanislav Sedov * 105*ae771770SStanislav Sedov * @subsection intro_krb5_auth_context Kerberos authentication context 106*ae771770SStanislav Sedov * 107*ae771770SStanislav Sedov * Kerberos authentication context (krb5_auth_context) holds all 108*ae771770SStanislav Sedov * context related to an authenticated connection, in a similar way to 109*ae771770SStanislav Sedov * the kerberos context that holds the context for the thread or 110*ae771770SStanislav Sedov * process. 111*ae771770SStanislav Sedov * 112*ae771770SStanislav Sedov * The krb5_auth_context is used by various functions that are 113*ae771770SStanislav Sedov * directly related to authentication between the 114*ae771770SStanislav Sedov * server/client. Example of data that this structure contains are 115*ae771770SStanislav Sedov * various flags, addresses of client and server, port numbers, 116*ae771770SStanislav Sedov * keyblocks (and subkeys), sequence numbers, replay cache, and 117*ae771770SStanislav Sedov * checksum types. 118*ae771770SStanislav Sedov * 119*ae771770SStanislav Sedov * @subsection intro_krb5_principal Kerberos principal 120*ae771770SStanislav Sedov * 121*ae771770SStanislav Sedov * The Kerberos principal is the structure that identifies a user or 122*ae771770SStanislav Sedov * service in Kerberos. The structure that holds the principal is the 123*ae771770SStanislav Sedov * krb5_principal. There are function to extract the realm and 124*ae771770SStanislav Sedov * elements of the principal, but most applications have no reason to 125*ae771770SStanislav Sedov * inspect the content of the structure. 126*ae771770SStanislav Sedov * 127*ae771770SStanislav Sedov * The are several ways to create a principal (with different degree of 128*ae771770SStanislav Sedov * portability), and one way to free it. 129*ae771770SStanislav Sedov * 130*ae771770SStanislav Sedov * See also the page @ref krb5_principal_intro for more information and also 131*ae771770SStanislav Sedov * module @ref krb5_principal. 132*ae771770SStanislav Sedov * 133*ae771770SStanislav Sedov * @subsection intro_krb5_ccache Credential cache 134*ae771770SStanislav Sedov * 135*ae771770SStanislav Sedov * A credential cache holds the tickets for a user. A given user can 136*ae771770SStanislav Sedov * have several credential caches, one for each realm where the user 137*ae771770SStanislav Sedov * have the initial tickets (the first krbtgt). 138*ae771770SStanislav Sedov * 139*ae771770SStanislav Sedov * The credential cache data can be stored internally in different 140*ae771770SStanislav Sedov * way, each of them for different proposes. File credential (FILE) 141*ae771770SStanislav Sedov * caches and processes based (KCM) caches are for permanent 142*ae771770SStanislav Sedov * storage. While memory caches (MEMORY) are local caches to the local 143*ae771770SStanislav Sedov * process. 144*ae771770SStanislav Sedov * 145*ae771770SStanislav Sedov * Caches are opened with krb5_cc_resolve() or created with 146*ae771770SStanislav Sedov * krb5_cc_new_unique(). 147*ae771770SStanislav Sedov * 148*ae771770SStanislav Sedov * If the cache needs to be opened again (using krb5_cc_resolve()) 149*ae771770SStanislav Sedov * krb5_cc_close() will close the handle, but not the remove the 150*ae771770SStanislav Sedov * cache. krb5_cc_destroy() will zero out the cache, remove the cache 151*ae771770SStanislav Sedov * so it can no longer be referenced. 152*ae771770SStanislav Sedov * 153*ae771770SStanislav Sedov * See also @ref krb5_ccache_intro and @ref krb5_ccache . 154*ae771770SStanislav Sedov * 155*ae771770SStanislav Sedov * @subsection intro_krb5_error_code Kerberos errors 156*ae771770SStanislav Sedov * 157*ae771770SStanislav Sedov * Kerberos errors are based on the com_err library. All error codes are 158*ae771770SStanislav Sedov * 32-bit signed numbers, the first 24 bits define what subsystem the 159*ae771770SStanislav Sedov * error originates from, and last 8 bits are 255 error codes within the 160*ae771770SStanislav Sedov * library. Each error code have fixed string associated with it. For 161*ae771770SStanislav Sedov * example, the error-code -1765328383 have the symbolic name 162*ae771770SStanislav Sedov * KRB5KDC_ERR_NAME_EXP, and associated error string ``Client's entry in 163*ae771770SStanislav Sedov * database has expired''. 164*ae771770SStanislav Sedov * 165*ae771770SStanislav Sedov * This is a great improvement compared to just getting one of the unix 166*ae771770SStanislav Sedov * error-codes back. However, Heimdal have an extention to pass back 167*ae771770SStanislav Sedov * customised errors messages. Instead of getting ``Key table entry not 168*ae771770SStanislav Sedov * found'', the user might back ``failed to find 169*ae771770SStanislav Sedov * host/host.example.com\@EXAMLE.COM(kvno 3) in keytab /etc/krb5.keytab 170*ae771770SStanislav Sedov * (des-cbc-crc)''. This improves the chance that the user find the 171*ae771770SStanislav Sedov * cause of the error so you should use the customised error message 172*ae771770SStanislav Sedov * whenever it's available. 173*ae771770SStanislav Sedov * 174*ae771770SStanislav Sedov * See also module @ref krb5_error . 175*ae771770SStanislav Sedov * 176*ae771770SStanislav Sedov * 177*ae771770SStanislav Sedov * @subsection intro_krb5_keytab Keytab management 178*ae771770SStanislav Sedov * 179*ae771770SStanislav Sedov * A keytab is a storage for locally stored keys. Heimdal includes keytab 180*ae771770SStanislav Sedov * support for Kerberos 5 keytabs, Kerberos 4 srvtab, AFS-KeyFile's, 181*ae771770SStanislav Sedov * and for storing keys in memory. 182*ae771770SStanislav Sedov * 183*ae771770SStanislav Sedov * Keytabs are used for servers and long-running services. 184*ae771770SStanislav Sedov * 185*ae771770SStanislav Sedov * See also @ref krb5_keytab_intro and @ref krb5_keytab . 186*ae771770SStanislav Sedov * 187*ae771770SStanislav Sedov * @subsection intro_krb5_crypto Kerberos crypto 188*ae771770SStanislav Sedov * 189*ae771770SStanislav Sedov * Heimdal includes a implementation of the Kerberos crypto framework, 190*ae771770SStanislav Sedov * all crypto operations. To create a crypto context call krb5_crypto_init(). 191*ae771770SStanislav Sedov * 192*ae771770SStanislav Sedov * See also module @ref krb5_crypto . 193*ae771770SStanislav Sedov * 194*ae771770SStanislav Sedov * @section kerberos5_client Walkthrough of a sample Kerberos 5 client 195*ae771770SStanislav Sedov * 196*ae771770SStanislav Sedov * This example contains parts of a sample TCP Kerberos 5 clients, if you 197*ae771770SStanislav Sedov * want a real working client, please look in appl/test directory in 198*ae771770SStanislav Sedov * the Heimdal distribution. 199*ae771770SStanislav Sedov * 200*ae771770SStanislav Sedov * All Kerberos error-codes that are returned from kerberos functions in 201*ae771770SStanislav Sedov * this program are passed to krb5_err, that will print a 202*ae771770SStanislav Sedov * descriptive text of the error code and exit. Graphical programs can 203*ae771770SStanislav Sedov * convert error-code to a human readable error-string with the 204*ae771770SStanislav Sedov * krb5_get_error_message() function. 205*ae771770SStanislav Sedov * 206*ae771770SStanislav Sedov * Note that you should not use any Kerberos function before 207*ae771770SStanislav Sedov * krb5_init_context() have completed successfully. That is the 208*ae771770SStanislav Sedov * reason err() is used when krb5_init_context() fails. 209*ae771770SStanislav Sedov * 210*ae771770SStanislav Sedov * First the client needs to call krb5_init_context to initialise 211*ae771770SStanislav Sedov * the Kerberos 5 library. This is only needed once per thread 212*ae771770SStanislav Sedov * in the program. If the function returns a non-zero value it indicates 213*ae771770SStanislav Sedov * that either the Kerberos implementation is failing or it's disabled on 214*ae771770SStanislav Sedov * this host. 215*ae771770SStanislav Sedov * 216*ae771770SStanislav Sedov * @code 217*ae771770SStanislav Sedov * #include <krb5.h> 218*ae771770SStanislav Sedov * 219*ae771770SStanislav Sedov * int 220*ae771770SStanislav Sedov * main(int argc, char **argv) 221*ae771770SStanislav Sedov * { 222*ae771770SStanislav Sedov * krb5_context context; 223*ae771770SStanislav Sedov * 224*ae771770SStanislav Sedov * if (krb5_init_context(&context)) 225*ae771770SStanislav Sedov * errx (1, "krb5_context"); 226*ae771770SStanislav Sedov * @endcode 227*ae771770SStanislav Sedov * 228*ae771770SStanislav Sedov * Now the client wants to connect to the host at the other end. The 229*ae771770SStanislav Sedov * preferred way of doing this is using getaddrinfo (for 230*ae771770SStanislav Sedov * operating system that have this function implemented), since getaddrinfo 231*ae771770SStanislav Sedov * is neutral to the address type and can use any protocol that is available. 232*ae771770SStanislav Sedov * 233*ae771770SStanislav Sedov * @code 234*ae771770SStanislav Sedov * struct addrinfo *ai, *a; 235*ae771770SStanislav Sedov * struct addrinfo hints; 236*ae771770SStanislav Sedov * int error; 237*ae771770SStanislav Sedov * 238*ae771770SStanislav Sedov * memset (&hints, 0, sizeof(hints)); 239*ae771770SStanislav Sedov * hints.ai_socktype = SOCK_STREAM; 240*ae771770SStanislav Sedov * hints.ai_protocol = IPPROTO_TCP; 241*ae771770SStanislav Sedov * 242*ae771770SStanislav Sedov * error = getaddrinfo (hostname, "pop3", &hints, &ai); 243*ae771770SStanislav Sedov * if (error) 244*ae771770SStanislav Sedov * errx (1, "%s: %s", hostname, gai_strerror(error)); 245*ae771770SStanislav Sedov * 246*ae771770SStanislav Sedov * for (a = ai; a != NULL; a = a->ai_next) { 247*ae771770SStanislav Sedov * int s; 248*ae771770SStanislav Sedov * 249*ae771770SStanislav Sedov * s = socket (a->ai_family, a->ai_socktype, a->ai_protocol); 250*ae771770SStanislav Sedov * if (s < 0) 251*ae771770SStanislav Sedov * continue; 252*ae771770SStanislav Sedov * if (connect (s, a->ai_addr, a->ai_addrlen) < 0) { 253*ae771770SStanislav Sedov * warn ("connect(%s)", hostname); 254*ae771770SStanislav Sedov * close (s); 255*ae771770SStanislav Sedov * continue; 256*ae771770SStanislav Sedov * } 257*ae771770SStanislav Sedov * freeaddrinfo (ai); 258*ae771770SStanislav Sedov * ai = NULL; 259*ae771770SStanislav Sedov * } 260*ae771770SStanislav Sedov * if (ai) { 261*ae771770SStanislav Sedov * freeaddrinfo (ai); 262*ae771770SStanislav Sedov * errx ("failed to contact %s", hostname); 263*ae771770SStanislav Sedov * } 264*ae771770SStanislav Sedov * @endcode 265*ae771770SStanislav Sedov * 266*ae771770SStanislav Sedov * Before authenticating, an authentication context needs to be 267*ae771770SStanislav Sedov * created. This context keeps all information for one (to be) authenticated 268*ae771770SStanislav Sedov * connection (see krb5_auth_context). 269*ae771770SStanislav Sedov * 270*ae771770SStanislav Sedov * @code 271*ae771770SStanislav Sedov * status = krb5_auth_con_init (context, &auth_context); 272*ae771770SStanislav Sedov * if (status) 273*ae771770SStanislav Sedov * krb5_err (context, 1, status, "krb5_auth_con_init"); 274*ae771770SStanislav Sedov * @endcode 275*ae771770SStanislav Sedov * 276*ae771770SStanislav Sedov * For setting the address in the authentication there is a help function 277*ae771770SStanislav Sedov * krb5_auth_con_setaddrs_from_fd() that does everything that is needed 278*ae771770SStanislav Sedov * when given a connected file descriptor to the socket. 279*ae771770SStanislav Sedov * 280*ae771770SStanislav Sedov * @code 281*ae771770SStanislav Sedov * status = krb5_auth_con_setaddrs_from_fd (context, 282*ae771770SStanislav Sedov * auth_context, 283*ae771770SStanislav Sedov * &sock); 284*ae771770SStanislav Sedov * if (status) 285*ae771770SStanislav Sedov * krb5_err (context, 1, status, 286*ae771770SStanislav Sedov * "krb5_auth_con_setaddrs_from_fd"); 287*ae771770SStanislav Sedov * @endcode 288*ae771770SStanislav Sedov * 289*ae771770SStanislav Sedov * The next step is to build a server principal for the service we want 290*ae771770SStanislav Sedov * to connect to. (See also krb5_sname_to_principal().) 291*ae771770SStanislav Sedov * 292*ae771770SStanislav Sedov * @code 293*ae771770SStanislav Sedov * status = krb5_sname_to_principal (context, 294*ae771770SStanislav Sedov * hostname, 295*ae771770SStanislav Sedov * service, 296*ae771770SStanislav Sedov * KRB5_NT_SRV_HST, 297*ae771770SStanislav Sedov * &server); 298*ae771770SStanislav Sedov * if (status) 299*ae771770SStanislav Sedov * krb5_err (context, 1, status, "krb5_sname_to_principal"); 300*ae771770SStanislav Sedov * @endcode 301*ae771770SStanislav Sedov * 302*ae771770SStanislav Sedov * The client principal is not passed to krb5_sendauth() 303*ae771770SStanislav Sedov * function, this causes the krb5_sendauth() function to try to figure it 304*ae771770SStanislav Sedov * out itself. 305*ae771770SStanislav Sedov * 306*ae771770SStanislav Sedov * The server program is using the function krb5_recvauth() to 307*ae771770SStanislav Sedov * receive the Kerberos 5 authenticator. 308*ae771770SStanislav Sedov * 309*ae771770SStanislav Sedov * In this case, mutual authentication will be tried. That means that the server 310*ae771770SStanislav Sedov * will authenticate to the client. Using mutual authentication 311*ae771770SStanislav Sedov * is good since it enables the user to verify that they are talking to the 312*ae771770SStanislav Sedov * right server (a server that knows the key). 313*ae771770SStanislav Sedov * 314*ae771770SStanislav Sedov * If you are using a non-blocking socket you will need to do all work of 315*ae771770SStanislav Sedov * krb5_sendauth() yourself. Basically you need to send over the 316*ae771770SStanislav Sedov * authenticator from krb5_mk_req() and, in case of mutual 317*ae771770SStanislav Sedov * authentication, verifying the result from the server with 318*ae771770SStanislav Sedov * krb5_rd_rep(). 319*ae771770SStanislav Sedov * 320*ae771770SStanislav Sedov * @code 321*ae771770SStanislav Sedov * status = krb5_sendauth (context, 322*ae771770SStanislav Sedov * &auth_context, 323*ae771770SStanislav Sedov * &sock, 324*ae771770SStanislav Sedov * VERSION, 325*ae771770SStanislav Sedov * NULL, 326*ae771770SStanislav Sedov * server, 327*ae771770SStanislav Sedov * AP_OPTS_MUTUAL_REQUIRED, 328*ae771770SStanislav Sedov * NULL, 329*ae771770SStanislav Sedov * NULL, 330*ae771770SStanislav Sedov * NULL, 331*ae771770SStanislav Sedov * NULL, 332*ae771770SStanislav Sedov * NULL, 333*ae771770SStanislav Sedov * NULL); 334*ae771770SStanislav Sedov * if (status) 335*ae771770SStanislav Sedov * krb5_err (context, 1, status, "krb5_sendauth"); 336*ae771770SStanislav Sedov * @endcode 337*ae771770SStanislav Sedov * 338*ae771770SStanislav Sedov * Once authentication has been performed, it is time to send some 339*ae771770SStanislav Sedov * data. First we create a krb5_data structure, then we sign it with 340*ae771770SStanislav Sedov * krb5_mk_safe() using the auth_context that contains the 341*ae771770SStanislav Sedov * session-key that was exchanged in the 342*ae771770SStanislav Sedov * krb5_sendauth()/krb5_recvauth() authentication 343*ae771770SStanislav Sedov * sequence. 344*ae771770SStanislav Sedov * 345*ae771770SStanislav Sedov * @code 346*ae771770SStanislav Sedov * data.data = "hej"; 347*ae771770SStanislav Sedov * data.length = 3; 348*ae771770SStanislav Sedov * 349*ae771770SStanislav Sedov * krb5_data_zero (&packet); 350*ae771770SStanislav Sedov * 351*ae771770SStanislav Sedov * status = krb5_mk_safe (context, 352*ae771770SStanislav Sedov * auth_context, 353*ae771770SStanislav Sedov * &data, 354*ae771770SStanislav Sedov * &packet, 355*ae771770SStanislav Sedov * NULL); 356*ae771770SStanislav Sedov * if (status) 357*ae771770SStanislav Sedov * krb5_err (context, 1, status, "krb5_mk_safe"); 358*ae771770SStanislav Sedov * @endcode 359*ae771770SStanislav Sedov * 360*ae771770SStanislav Sedov * And send it over the network. 361*ae771770SStanislav Sedov * 362*ae771770SStanislav Sedov * @code 363*ae771770SStanislav Sedov * len = packet.length; 364*ae771770SStanislav Sedov * net_len = htonl(len); 365*ae771770SStanislav Sedov * 366*ae771770SStanislav Sedov * if (krb5_net_write (context, &sock, &net_len, 4) != 4) 367*ae771770SStanislav Sedov * err (1, "krb5_net_write"); 368*ae771770SStanislav Sedov * if (krb5_net_write (context, &sock, packet.data, len) != len) 369*ae771770SStanislav Sedov * err (1, "krb5_net_write"); 370*ae771770SStanislav Sedov * @endcode 371*ae771770SStanislav Sedov * 372*ae771770SStanislav Sedov * To send encrypted (and signed) data krb5_mk_priv() should be 373*ae771770SStanislav Sedov * used instead. krb5_mk_priv() works the same way as 374*ae771770SStanislav Sedov * krb5_mk_safe(), with the exception that it encrypts the data 375*ae771770SStanislav Sedov * in addition to signing it. 376*ae771770SStanislav Sedov * 377*ae771770SStanislav Sedov * @code 378*ae771770SStanislav Sedov * data.data = "hemligt"; 379*ae771770SStanislav Sedov * data.length = 7; 380*ae771770SStanislav Sedov * 381*ae771770SStanislav Sedov * krb5_data_free (&packet); 382*ae771770SStanislav Sedov * 383*ae771770SStanislav Sedov * status = krb5_mk_priv (context, 384*ae771770SStanislav Sedov * auth_context, 385*ae771770SStanislav Sedov * &data, 386*ae771770SStanislav Sedov * &packet, 387*ae771770SStanislav Sedov * NULL); 388*ae771770SStanislav Sedov * if (status) 389*ae771770SStanislav Sedov * krb5_err (context, 1, status, "krb5_mk_priv"); 390*ae771770SStanislav Sedov * @endcode 391*ae771770SStanislav Sedov * 392*ae771770SStanislav Sedov * And send it over the network. 393*ae771770SStanislav Sedov * 394*ae771770SStanislav Sedov * @code 395*ae771770SStanislav Sedov * len = packet.length; 396*ae771770SStanislav Sedov * net_len = htonl(len); 397*ae771770SStanislav Sedov * 398*ae771770SStanislav Sedov * if (krb5_net_write (context, &sock, &net_len, 4) != 4) 399*ae771770SStanislav Sedov * err (1, "krb5_net_write"); 400*ae771770SStanislav Sedov * if (krb5_net_write (context, &sock, packet.data, len) != len) 401*ae771770SStanislav Sedov * err (1, "krb5_net_write"); 402*ae771770SStanislav Sedov * 403*ae771770SStanislav Sedov * @endcode 404*ae771770SStanislav Sedov * 405*ae771770SStanislav Sedov * The server is using krb5_rd_safe() and 406*ae771770SStanislav Sedov * krb5_rd_priv() to verify the signature and decrypt the packet. 407*ae771770SStanislav Sedov * 408*ae771770SStanislav Sedov * @section intro_krb5_verify_user Validating a password in an application 409*ae771770SStanislav Sedov * 410*ae771770SStanislav Sedov * See the manual page for krb5_verify_user(). 411*ae771770SStanislav Sedov * 412*ae771770SStanislav Sedov * @section mit_differences API differences to MIT Kerberos 413*ae771770SStanislav Sedov * 414*ae771770SStanislav Sedov * This section is somewhat disorganised, but so far there is no overall 415*ae771770SStanislav Sedov * structure to the differences, though some of the have their root in 416*ae771770SStanislav Sedov * that Heimdal uses an ASN.1 compiler and MIT doesn't. 417*ae771770SStanislav Sedov * 418*ae771770SStanislav Sedov * @subsection mit_krb5_principal Principal and realms 419*ae771770SStanislav Sedov * 420*ae771770SStanislav Sedov * Heimdal stores the realm as a krb5_realm, that is a char *. 421*ae771770SStanislav Sedov * MIT Kerberos uses a krb5_data to store a realm. 422*ae771770SStanislav Sedov * 423*ae771770SStanislav Sedov * In Heimdal krb5_principal doesn't contain the component 424*ae771770SStanislav Sedov * name_type; it's instead stored in component 425*ae771770SStanislav Sedov * name.name_type. To get and set the nametype in Heimdal, use 426*ae771770SStanislav Sedov * krb5_principal_get_type() and 427*ae771770SStanislav Sedov * krb5_principal_set_type(). 428*ae771770SStanislav Sedov * 429*ae771770SStanislav Sedov * For more information about principal and realms, see 430*ae771770SStanislav Sedov * krb5_principal. 431*ae771770SStanislav Sedov * 432*ae771770SStanislav Sedov * @subsection mit_krb5_error_code Error messages 433*ae771770SStanislav Sedov * 434*ae771770SStanislav Sedov * To get the error string, Heimdal uses 435*ae771770SStanislav Sedov * krb5_get_error_message(). This is to return custom error messages 436*ae771770SStanislav Sedov * (like ``Can't find host/datan.example.com\@CODE.COM in 437*ae771770SStanislav Sedov * /etc/krb5.conf.'' instead of a ``Key table entry not found'' that 438*ae771770SStanislav Sedov * error_message returns. 439*ae771770SStanislav Sedov * 440*ae771770SStanislav Sedov * Heimdal uses a threadsafe(r) version of the com_err interface; the 441*ae771770SStanislav Sedov * global com_err table isn't initialised. Then 442*ae771770SStanislav Sedov * error_message returns quite a boring error string (just 443*ae771770SStanislav Sedov * the error code itself). 444*ae771770SStanislav Sedov * 445*ae771770SStanislav Sedov * 446*ae771770SStanislav Sedov */ 447*ae771770SStanislav Sedov 448*ae771770SStanislav Sedov /** 449*ae771770SStanislav Sedov * 450*ae771770SStanislav Sedov * 451*ae771770SStanislav Sedov * @page krb5_fileformats File formats 452*ae771770SStanislav Sedov * 453*ae771770SStanislav Sedov * @section fileformats File formats 454*ae771770SStanislav Sedov * 455*ae771770SStanislav Sedov * This section documents the diffrent file formats that are used in 456*ae771770SStanislav Sedov * Heimdal and other Kerberos implementations. 457*ae771770SStanislav Sedov * 458*ae771770SStanislav Sedov * @subsection file_keytab keytab 459*ae771770SStanislav Sedov * 460*ae771770SStanislav Sedov * The keytab binary format is not a standard format. The format has 461*ae771770SStanislav Sedov * evolved and may continue to. It is however understood by several 462*ae771770SStanislav Sedov * Kerberos implementations including Heimdal, MIT, Sun's Java ktab and 463*ae771770SStanislav Sedov * are created by the ktpass.exe utility from Windows. So it has 464*ae771770SStanislav Sedov * established itself as the defacto format for storing Kerberos keys. 465*ae771770SStanislav Sedov * 466*ae771770SStanislav Sedov * The following C-like structure definitions illustrate the MIT keytab 467*ae771770SStanislav Sedov * file format. All values are in network byte order. All text is ASCII. 468*ae771770SStanislav Sedov * 469*ae771770SStanislav Sedov * @code 470*ae771770SStanislav Sedov * keytab { 471*ae771770SStanislav Sedov * uint16_t file_format_version; # 0x502 472*ae771770SStanislav Sedov * keytab_entry entries[*]; 473*ae771770SStanislav Sedov * }; 474*ae771770SStanislav Sedov * 475*ae771770SStanislav Sedov * keytab_entry { 476*ae771770SStanislav Sedov * int32_t size; 477*ae771770SStanislav Sedov * uint16_t num_components; # subtract 1 if version 0x501 478*ae771770SStanislav Sedov * counted_octet_string realm; 479*ae771770SStanislav Sedov * counted_octet_string components[num_components]; 480*ae771770SStanislav Sedov * uint32_t name_type; # not present if version 0x501 481*ae771770SStanislav Sedov * uint32_t timestamp; 482*ae771770SStanislav Sedov * uint8_t vno8; 483*ae771770SStanislav Sedov * keyblock key; 484*ae771770SStanislav Sedov * uint32_t vno; #only present if >= 4 bytes left in entry 485*ae771770SStanislav Sedov * uint32_t flags; #only present if >= 4 bytes left in entry 486*ae771770SStanislav Sedov * }; 487*ae771770SStanislav Sedov * 488*ae771770SStanislav Sedov * counted_octet_string { 489*ae771770SStanislav Sedov * uint16_t length; 490*ae771770SStanislav Sedov * uint8_t data[length]; 491*ae771770SStanislav Sedov * }; 492*ae771770SStanislav Sedov * 493*ae771770SStanislav Sedov * keyblock { 494*ae771770SStanislav Sedov * uint16_t type; 495*ae771770SStanislav Sedov * counted_octet_string; 496*ae771770SStanislav Sedov * }; 497*ae771770SStanislav Sedov * @endcode 498*ae771770SStanislav Sedov * 499*ae771770SStanislav Sedov * All numbers are stored in network byteorder (big endian) format. 500*ae771770SStanislav Sedov * 501*ae771770SStanislav Sedov * The keytab file format begins with the 16 bit file_format_version which 502*ae771770SStanislav Sedov * at the time this document was authored is 0x502. The format of older 503*ae771770SStanislav Sedov * keytabs is described at the end of this document. 504*ae771770SStanislav Sedov * 505*ae771770SStanislav Sedov * The file_format_version is immediately followed by an array of 506*ae771770SStanislav Sedov * keytab_entry structures which are prefixed with a 32 bit size indicating 507*ae771770SStanislav Sedov * the number of bytes that follow in the entry. Note that the size should be 508*ae771770SStanislav Sedov * evaluated as signed. This is because a negative value indicates that the 509*ae771770SStanislav Sedov * entry is in fact empty (e.g. it has been deleted) and that the negative 510*ae771770SStanislav Sedov * value of that negative value (which is of course a positive value) is 511*ae771770SStanislav Sedov * the offset to the next keytab_entry. Based on these size values alone 512*ae771770SStanislav Sedov * the entire keytab file can be traversed. 513*ae771770SStanislav Sedov * 514*ae771770SStanislav Sedov * The size is followed by a 16 bit num_components field indicating the 515*ae771770SStanislav Sedov * number of counted_octet_string components in the components array. 516*ae771770SStanislav Sedov * 517*ae771770SStanislav Sedov * The num_components field is followed by a counted_octet_string 518*ae771770SStanislav Sedov * representing the realm of the principal. 519*ae771770SStanislav Sedov * 520*ae771770SStanislav Sedov * A counted_octet_string is simply an array of bytes prefixed with a 16 521*ae771770SStanislav Sedov * bit length. For the realm and name components, the counted_octet_string 522*ae771770SStanislav Sedov * bytes are ASCII encoded text with no zero terminator. 523*ae771770SStanislav Sedov * 524*ae771770SStanislav Sedov * Following the realm is the components array that represents the name of 525*ae771770SStanislav Sedov * the principal. The text of these components may be joined with slashs 526*ae771770SStanislav Sedov * to construct the typical SPN representation. For example, the service 527*ae771770SStanislav Sedov * principal HTTP/www.foo.net\@FOO.NET would consist of name components 528*ae771770SStanislav Sedov * "HTTP" followed by "www.foo.net". 529*ae771770SStanislav Sedov * 530*ae771770SStanislav Sedov * Following the components array is the 32 bit name_type (e.g. 1 is 531*ae771770SStanislav Sedov * KRB5_NT_PRINCIPAL, 2 is KRB5_NT_SRV_INST, 5 is KRB5_NT_UID, etc). In 532*ae771770SStanislav Sedov * practice the name_type is almost certainly 1 meaning KRB5_NT_PRINCIPAL. 533*ae771770SStanislav Sedov * 534*ae771770SStanislav Sedov * The 32 bit timestamp indicates the time the key was established for that 535*ae771770SStanislav Sedov * principal. The value represents the number of seconds since Jan 1, 1970. 536*ae771770SStanislav Sedov * 537*ae771770SStanislav Sedov * The 8 bit vno8 field is the version number of the key. This value is 538*ae771770SStanislav Sedov * overridden by the 32 bit vno field if it is present. The vno8 field is 539*ae771770SStanislav Sedov * filled with the lower 8 bits of the 32 bit protocol kvno field. 540*ae771770SStanislav Sedov * 541*ae771770SStanislav Sedov * The keyblock structure consists of a 16 bit value indicating the 542*ae771770SStanislav Sedov * encryption type and is a counted_octet_string containing the key. The 543*ae771770SStanislav Sedov * encryption type is the same as the Kerberos standard (e.g. 3 is 544*ae771770SStanislav Sedov * des-cbc-md5, 23 is arcfour-hmac-md5, etc). 545*ae771770SStanislav Sedov * 546*ae771770SStanislav Sedov * The last field of the keytab_entry structure is optional. If the size of 547*ae771770SStanislav Sedov * the keytab_entry indicates that there are at least 4 bytes remaining, 548*ae771770SStanislav Sedov * a 32 bit value representing the key version number is present. This 549*ae771770SStanislav Sedov * value supersedes the 8 bit vno8 value preceeding the keyblock. 550*ae771770SStanislav Sedov * 551*ae771770SStanislav Sedov * Older keytabs with a file_format_version of 0x501 are different in 552*ae771770SStanislav Sedov * three ways: 553*ae771770SStanislav Sedov * 554*ae771770SStanislav Sedov * - All integers are in host byte order [1]. 555*ae771770SStanislav Sedov * - The num_components field is 1 too large (i.e. after decoding, decrement by 1). 556*ae771770SStanislav Sedov * - The 32 bit name_type field is not present. 557*ae771770SStanislav Sedov * 558*ae771770SStanislav Sedov * [1] The file_format_version field should really be treated as two 559*ae771770SStanislav Sedov * separate 8 bit quantities representing the major and minor version 560*ae771770SStanislav Sedov * number respectively. 561*ae771770SStanislav Sedov * 562*ae771770SStanislav Sedov * @subsection file_hdb_dump Heimdal database dump file 563*ae771770SStanislav Sedov * 564*ae771770SStanislav Sedov * Format of the Heimdal text dump file as of Heimdal 0.6.3: 565*ae771770SStanislav Sedov * 566*ae771770SStanislav Sedov * Each line in the dump file is one entry in the database. 567*ae771770SStanislav Sedov * 568*ae771770SStanislav Sedov * Each field of a line is separated by one or more spaces, with the 569*ae771770SStanislav Sedov * exception of fields consisting of principals containing spaces, where 570*ae771770SStanislav Sedov * space can be quoted with \ and \ is quoted by \. 571*ae771770SStanislav Sedov * 572*ae771770SStanislav Sedov * Fields and their types are: 573*ae771770SStanislav Sedov * 574*ae771770SStanislav Sedov * @code 575*ae771770SStanislav Sedov * Quoted princial (quote character is \) [string] 576*ae771770SStanislav Sedov * Keys [keys] 577*ae771770SStanislav Sedov * Created by [event] 578*ae771770SStanislav Sedov * Modified by [event optional] 579*ae771770SStanislav Sedov * Valid start time [time optional] 580*ae771770SStanislav Sedov * Valid end time [time optional] 581*ae771770SStanislav Sedov * Password end valid time [time optional] 582*ae771770SStanislav Sedov * Max lifetime of ticket [time optional] 583*ae771770SStanislav Sedov * Max renew time of ticket [integer optional] 584*ae771770SStanislav Sedov * Flags [hdb flags] 585*ae771770SStanislav Sedov * Generation number [generation optional] 586*ae771770SStanislav Sedov * Extensions [extentions optional] 587*ae771770SStanislav Sedov * @endcode 588*ae771770SStanislav Sedov * 589*ae771770SStanislav Sedov * Fields following these silently are ignored. 590*ae771770SStanislav Sedov * 591*ae771770SStanislav Sedov * All optional fields will be skipped if they fail to parse (or comprise 592*ae771770SStanislav Sedov * the optional field marker of "-", w/o quotes). 593*ae771770SStanislav Sedov * 594*ae771770SStanislav Sedov * Example: 595*ae771770SStanislav Sedov * 596*ae771770SStanislav Sedov * @code 597*ae771770SStanislav Sedov * fred\@CODE.COM 27:1:16:e8b4c8fc7e60b9e641dcf4cff3f08a701d982a2f89ba373733d26ca59ba6c789666f6b8bfcf169412bb1e5dceb9b33cda29f3412:-:1:3:4498a933881178c744f4232172dcd774c64e81fa6d05ecdf643a7e390624a0ebf3c7407a:-:1:2:b01934b13eb795d76f3a80717d469639b4da0cfb644161340ef44fdeb375e54d684dbb85:-:1:1:ea8e16d8078bf60c781da90f508d4deccba70595258b9d31888d33987cd31af0c9cced2e:- 20020415130120:admin\@CODE.COM 20041221112428:fred\@CODE.COM - - - 86400 604800 126 20020415130120:793707:28 - 598*ae771770SStanislav Sedov * @endcode 599*ae771770SStanislav Sedov * 600*ae771770SStanislav Sedov * Encoding of types are as follows: 601*ae771770SStanislav Sedov * 602*ae771770SStanislav Sedov * - keys 603*ae771770SStanislav Sedov * 604*ae771770SStanislav Sedov * @code 605*ae771770SStanislav Sedov * kvno:[masterkvno:keytype:keydata:salt]{zero or more separated by :} 606*ae771770SStanislav Sedov * @endcode 607*ae771770SStanislav Sedov * 608*ae771770SStanislav Sedov * kvno is the key version number. 609*ae771770SStanislav Sedov * 610*ae771770SStanislav Sedov * keydata is hex-encoded 611*ae771770SStanislav Sedov * 612*ae771770SStanislav Sedov * masterkvno is the kvno of the database master key. If this field is 613*ae771770SStanislav Sedov * empty, the kadmin load and merge operations will encrypt the key data 614*ae771770SStanislav Sedov * with the master key if there is one. Otherwise the key data will be 615*ae771770SStanislav Sedov * imported asis. 616*ae771770SStanislav Sedov * 617*ae771770SStanislav Sedov * salt is encoded as "-" (no/default salt) or 618*ae771770SStanislav Sedov * 619*ae771770SStanislav Sedov * @code 620*ae771770SStanislav Sedov * salt-type / 621*ae771770SStanislav Sedov * salt-type / "string" 622*ae771770SStanislav Sedov * salt-type / hex-encoded-data 623*ae771770SStanislav Sedov * @endcode 624*ae771770SStanislav Sedov * 625*ae771770SStanislav Sedov * keytype is the protocol enctype number; see enum ENCTYPE in 626*ae771770SStanislav Sedov * include/krb5_asn1.h for values. 627*ae771770SStanislav Sedov * 628*ae771770SStanislav Sedov * Example: 629*ae771770SStanislav Sedov * @code 630*ae771770SStanislav Sedov * 27:1:16:e8b4c8fc7e60b9e641dcf4cff3f08a701d982a2f89ba373733d26ca59ba6c789666f6b8bfcf169412bb1e5dceb9b33cda29f3412:-:1:3:4498a933881178c744f4232172dcd774c64e81fa6d05ecdf643a7e390624a0ebf3c7407a:-:1:2:b01934b13eb795d76f3a80717d469639b4da0cfb644161340ef44fdeb375e54d684dbb85:-:1:1:ea8e16d8078bf60c781da90f508d4deccba70595258b9d31888d33987cd31af0c9cced2e:- 631*ae771770SStanislav Sedov * @endcode 632*ae771770SStanislav Sedov * 633*ae771770SStanislav Sedov * 634*ae771770SStanislav Sedov * @code 635*ae771770SStanislav Sedov * kvno=27,{key: masterkvno=1,keytype=des3-cbc-sha1,keydata=..., default salt}... 636*ae771770SStanislav Sedov * @endcode 637*ae771770SStanislav Sedov * 638*ae771770SStanislav Sedov * - time 639*ae771770SStanislav Sedov * 640*ae771770SStanislav Sedov * Format of the time is: YYYYmmddHHMMSS, corresponding to strftime 641*ae771770SStanislav Sedov * format "%Y%m%d%k%M%S". 642*ae771770SStanislav Sedov * 643*ae771770SStanislav Sedov * Time is expressed in UTC. 644*ae771770SStanislav Sedov * 645*ae771770SStanislav Sedov * Time can be optional (using -), when the time 0 is used. 646*ae771770SStanislav Sedov * 647*ae771770SStanislav Sedov * Example: 648*ae771770SStanislav Sedov * 649*ae771770SStanislav Sedov * @code 650*ae771770SStanislav Sedov * 20041221112428 651*ae771770SStanislav Sedov * @endcode 652*ae771770SStanislav Sedov * 653*ae771770SStanislav Sedov * - event 654*ae771770SStanislav Sedov * 655*ae771770SStanislav Sedov * @code 656*ae771770SStanislav Sedov * time:principal 657*ae771770SStanislav Sedov * @endcode 658*ae771770SStanislav Sedov * 659*ae771770SStanislav Sedov * time is as given in format time 660*ae771770SStanislav Sedov * 661*ae771770SStanislav Sedov * principal is a string. Not quoting it may not work in earlier 662*ae771770SStanislav Sedov * versions of Heimdal. 663*ae771770SStanislav Sedov * 664*ae771770SStanislav Sedov * Example: 665*ae771770SStanislav Sedov * @code 666*ae771770SStanislav Sedov * 20041221112428:bloggs\@CODE.COM 667*ae771770SStanislav Sedov * @endcode 668*ae771770SStanislav Sedov * 669*ae771770SStanislav Sedov * - hdb flags 670*ae771770SStanislav Sedov * 671*ae771770SStanislav Sedov * Integer encoding of HDB flags, see HDBFlags in lib/hdb/hdb.asn1. Each 672*ae771770SStanislav Sedov * bit in the integer is the same as the bit in the specification. 673*ae771770SStanislav Sedov * 674*ae771770SStanislav Sedov * - generation: 675*ae771770SStanislav Sedov * 676*ae771770SStanislav Sedov * @code 677*ae771770SStanislav Sedov * time:usec:gen 678*ae771770SStanislav Sedov * @endcode 679*ae771770SStanislav Sedov * 680*ae771770SStanislav Sedov * 681*ae771770SStanislav Sedov * usec is a the microsecond, integer. 682*ae771770SStanislav Sedov * gen is generation number, integer. 683*ae771770SStanislav Sedov * 684*ae771770SStanislav Sedov * The generation can be defaulted (using '-') or the empty string 685*ae771770SStanislav Sedov * 686*ae771770SStanislav Sedov * - extensions: 687*ae771770SStanislav Sedov * 688*ae771770SStanislav Sedov * @code 689*ae771770SStanislav Sedov * first-hex-encoded-HDB-Extension[:second-...] 690*ae771770SStanislav Sedov * @endcode 691*ae771770SStanislav Sedov * 692*ae771770SStanislav Sedov * HDB-extension is encoded the DER encoded HDB-Extension from 693*ae771770SStanislav Sedov * lib/hdb/hdb.asn1. Consumers HDB extensions should be aware that 694*ae771770SStanislav Sedov * unknown entires needs to be preserved even thought the ASN.1 data 695*ae771770SStanislav Sedov * content might be unknown. There is a critical flag in the data to show 696*ae771770SStanislav Sedov * to the KDC that the entry MUST be understod if the entry is to be 697*ae771770SStanislav Sedov * used. 698*ae771770SStanislav Sedov * 699*ae771770SStanislav Sedov * 700*ae771770SStanislav Sedov */ 701