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