1*ebfedea0SLionel SambucSASL client library - draft 2*ebfedea0SLionel Sambuc--------------------------- 3*ebfedea0SLionel Sambuc 4*ebfedea0SLionel SambucVersion: $NetBSD: library.txt,v 1.3 2011/02/11 23:44:42 christos Exp $ 5*ebfedea0SLionel Sambuc 6*ebfedea0SLionel Sambuc1. Typedefs 7*ebfedea0SLionel Sambuc 8*ebfedea0SLionel SambucMoved to src/*.h 9*ebfedea0SLionel Sambuc 10*ebfedea0SLionel Sambuc2. Public API 11*ebfedea0SLionel Sambuc 12*ebfedea0SLionel Sambucsaslc_t *saslc_init(const char *appname); - Function takes appname as an 13*ebfedea0SLionel Sambucargument, function allocates and initializes new saslc_t structure, parses 14*ebfedea0SLionel Sambucconfiguration files if available (/etc/saslc/appname.d/sasl.conf and then 15*ebfedea0SLionel Sambuc/etc/saslc/appname.d/mechanism.conf for machanisms which are listed in 16*ebfedea0SLionel Sambucsasl.conf) Function returns pointer to the saslc_t on success and NULL on 17*ebfedea0SLionel Sambucfailure. 18*ebfedea0SLionel Sambuc 19*ebfedea0SLionel Sambucconst char *saslc_strerror(saslc_t *saslc); - function maps last error 20*ebfedea0SLionel Sambucnumber in saslc to the message string. Returns pointer to the message string 21*ebfedea0SLionel Sambucon success and pointer to the "unknown error" string on failure. 22*ebfedea0SLionel Sambuc 23*ebfedea0SLionel Sambucint saslc_end(saslc_t *saslc); - function destroys SASL library context and 24*ebfedea0SLionel Sambucdeallocates any resources used. If any sessions are assigned to the context 25*ebfedea0SLionel Sambucthen function closes them. It returns 0 on success and -1 on failure. 26*ebfedea0SLionel Sambuc 27*ebfedea0SLionel Sambucsaslc_sess_t *saslc_sess_init(saslc_t *saslc, const char *mechs); - Function 28*ebfedea0SLionel Sambuccreates a new sasl session. If saslc is NULL then default configuration 29*ebfedea0SLionel Sambucsettings are used. Mechs is the string which consists of a comma separated 30*ebfedea0SLionel Sambuclist of mechanism names. Mechanism used for the authentication is selected 31*ebfedea0SLionel Sambucbasing on the configuration. Function allocates saslc_sess_t and performs 32*ebfedea0SLionel Sambucinitialization of saslc_sess_t, pointer to it is returned on success and NULL 33*ebfedea0SLionel Sambucis returned on failure. In case of a failure saslc errno is set. 34*ebfedea0SLionel Sambuc 35*ebfedea0SLionel Sambucint saslc_sess_setprop(saslc_sess_t *sess, const char *name, 36*ebfedea0SLionel Sambuc const char *value); - Functions sets a property in the session. This 37*ebfedea0SLionel Sambucfunction is used for setting i.e. callbacks. It returns 0 on success and -1 38*ebfedea0SLionel Sambucon failure. In case of a failure sess errno is set. 39*ebfedea0SLionel Sambuc 40*ebfedea0SLionel SambucNOTE: Property is added to the sess->prop dictionary. 41*ebfedea0SLionel SambucNOTE: All properties' names should match to [A-Za-z0-9_]+. 42*ebfedea0SLionel Sambuc 43*ebfedea0SLionel Sambucconst char *saslc_sess_getprop(saslc_sess_t *sess, const char *name); - 44*ebfedea0SLionel SambucFunction gets property from the session. It return pointer to the property 45*ebfedea0SLionel Sambucvalue on success and NULL on failure. In case of a failure sess errno is 46*ebfedea0SLionel Sambucset. 47*ebfedea0SLionel Sambuc 48*ebfedea0SLionel SambucNOTE: Property is taken from the sess->prop dictionary, if property not exist 49*ebfedea0SLionel Sambucthen sess->context->prop is used with added sess->mech->name."-" prefix. 50*ebfedea0SLionel Sambuc 51*ebfedea0SLionel Sambucint saslc_sess_cont(saslc_sess_t *sess, const char *in, size_t inlen, 52*ebfedea0SLionel Sambuc char **out, size_t *outlen); - Function performs one step of the SASL 53*ebfedea0SLionel Sambucauthentication. Input data of length inlen is passed in the "in" argument. 54*ebfedea0SLionel SambucFunction stores output of length outlen in the out argument and returns 0 on 55*ebfedea0SLionel Sambucsuccess, 1 if more steps of the SASL authentication is needed and -1 on 56*ebfedea0SLionel Sambucfailure. In case of a failure sess errno is set. 57*ebfedea0SLionel Sambuc 58*ebfedea0SLionel SambucNOTE: user is responsible for deallocate the output data. 59*ebfedea0SLionel SambucIMPLEMENTATION: sess->mech->cont(sess, in, inlen, out, outlen) 60*ebfedea0SLionel Sambuc 61*ebfedea0SLionel Sambucconst char *saslc_sess_strerror(saslc_sess_t *sess); - function maps last 62*ebfedea0SLionel Sambucerror number in sess to message string. Returns pointer to the message string 63*ebfedea0SLionel Sambucon success and pointer to the "unknown error" string on failure. 64*ebfedea0SLionel Sambuc 65*ebfedea0SLionel Sambucconst char *saslc_sess_strmech(saslc_sess_t *sess); - function returns pointer 66*ebfedea0SLionel Sambucto the string contains name of the mechanism used in session. On failure 67*ebfedea0SLionel Sambucfunction returns pointer to "unknown". 68*ebfedea0SLionel Sambuc 69*ebfedea0SLionel Sambucint saslc_sess_encode(saslc_sess_t *sess, const char *in, size_t inlen, 70*ebfedea0SLionel Sambuc char **out, size_t *outlen); - function encodes data using security layer 71*ebfedea0SLionel Sambucnegotiated during the authentication. Returns 0 on success, -1 on failure. In 72*ebfedea0SLionel Sambuccase of a failure sess errno is set. 73*ebfedea0SLionel SambucIMPLEMENTATION: sess->mech->encode(sess, in, inlen, out, outlen) 74*ebfedea0SLionel Sambuc 75*ebfedea0SLionel Sambucint saslc_sess_decode(saslc_sess_t *sess, const char *in, size_t inlen, 76*ebfedea0SLionel Sambuc char **out, size_t *outlen); - function decodes data using security layer 77*ebfedea0SLionel Sambucnegotiated during the authentication. Returns 0 on success, -1 on failure. In 78*ebfedea0SLionel Sambuccase of a failure sess errno is set. 79*ebfedea0SLionel SambucIMPLEMENTATION: sess->mech->decode(sess, in, inlen, out, outlen) 80*ebfedea0SLionel Sambuc 81*ebfedea0SLionel Sambucvoid saslc_sess_end(saslc_sess_t *sess); - function destroys SASL session and 82*ebfedea0SLionel Sambucdeallocates any resources used. 83*ebfedea0SLionel Sambuc 84*ebfedea0SLionel Sambuc3. Mechanisms 85*ebfedea0SLionel Sambuc 86*ebfedea0SLionel Sambuc3.1. Global mechanisms table 87*ebfedea0SLionel Sambuc 88*ebfedea0SLionel Sambucsaslc_mech_list_t *mechanisms; 89*ebfedea0SLionel Sambuc 90*ebfedea0SLionel SambucList of mechanisms, initialized during first call of saslc_start(...); 91*ebfedea0SLionel Sambuc 92*ebfedea0SLionel Sambuc3.3. Mechanisms implementation 93*ebfedea0SLionel Sambuc 94*ebfedea0SLionel SambucEach mechanism will provide const saslc_mech_t structure describing its 95*ebfedea0SLionel Sambucimplementation. Mechanisms state is described by saslc_mech_sess_t, using this 96*ebfedea0SLionel Sambuctype by mechanism is not mandatory and different struct can be defined by a 97*ebfedea0SLionel Sambucmechanism if necessary. This structure is used only for representing internal 98*ebfedea0SLionel Sambucstate of the mechanism session, and wouldn't be used outside of mechanism 99*ebfedea0SLionel Sambucimplementation. 100*ebfedea0SLionel Sambuc 101*ebfedea0SLionel Sambuc3.2. Mechanisms which are going to be implemented 102*ebfedea0SLionel Sambuc 103*ebfedea0SLionel Sambuc * ANONYMOUS (create, destroy, cont) 104*ebfedea0SLionel Sambuc * EXTERNAL (create, destroy, cont) 105*ebfedea0SLionel Sambuc * PLAIN (create, destroy, cont) 106*ebfedea0SLionel Sambuc * LOGIN (create, destroy, cont) 107*ebfedea0SLionel Sambuc * CRAM-MD5 (create, destroy, cont) 108*ebfedea0SLionel Sambuc * DIGEST-MD5 (create, destroy, cont, encode, decode) 109*ebfedea0SLionel Sambuc * GSSAPI (create, destroy, cont, encode, decode) 110*ebfedea0SLionel Sambuc 111*ebfedea0SLionel Sambuc3.3. Example 112*ebfedea0SLionel Sambuc 113*ebfedea0SLionel Sambuc Consider ANONYMOUS mechanism as example, its pseudo implementation looks as 114*ebfedea0SLionel Sambucfollows: 115*ebfedea0SLionel Sambuc 116*ebfedea0SLionel Sambucgeneric_create(...) { 117*ebfedea0SLionel Sambuc // create mech_sess structure 118*ebfedea0SLionel Sambuc // mech_sess->status = AUTHENTICATION 119*ebfedea0SLionel Sambuc} 120*ebfedea0SLionel Sambuc 121*ebfedea0SLionel Sambucanon_cont(...) { 122*ebfedea0SLionel Sambuc char *token; 123*ebfedea0SLionel Sambuc 124*ebfedea0SLionel Sambuc if ( mech_sess->status != AUTHENTICATION ) { 125*ebfedea0SLionel Sambuc // error handler 126*ebfedea0SLionel Sambuc } 127*ebfedea0SLionel Sambuc 128*ebfedea0SLionel Sambuc // get token from session if present, if not use default from 129*ebfedea0SLionel Sambuc // configuration 130*ebfedea0SLionel Sambuc 131*ebfedea0SLionel Sambuc // output = token, outlen = lenght(token) 132*ebfedea0SLionel Sambuc // mech_sess->status = AUTHENTICATED... 133*ebfedea0SLionel Sambuc // return 0; 134*ebfedea0SLionel Sambuc} 135*ebfedea0SLionel Sambuc 136*ebfedea0SLionel Sambucgeneric_destroy(...) { 137*ebfedea0SLionel Sambuc // destroy mech_sess structure 138*ebfedea0SLionel Sambuc // return 139*ebfedea0SLionel Sambuc} 140*ebfedea0SLionel Sambuc 141*ebfedea0SLionel Sambucsaslc_mech_t anon_mech = { 142*ebfedea0SLionel Sambuc "ANONYMOUS", // const char *name; 143*ebfedea0SLionel Sambuc FLAG_ANONYMOUS, /* mechanism flags */ 144*ebfedea0SLionel Sambuc mech_generic_create; /* create function - creates mechanism 145*ebfedea0SLionel Sambuc instance */ 146*ebfedea0SLionel Sambuc mech_anonymous_cont; /* step function - performs one step of 147*ebfedea0SLionel Sambuc authentication */ 148*ebfedea0SLionel Sambuc NULL; /* encoding function - encodes input 149*ebfedea0SLionel Sambuc according to negotiated security layer */ 150*ebfedea0SLionel Sambuc NULL; /* decoding function - decodes input 151*ebfedea0SLionel Sambuc according to negotiated security layer */ 152*ebfedea0SLionel Sambuc mech_generic_destroy; /* destroy function - destroys mechanism 153*ebfedea0SLionel Sambuc instance */ 154*ebfedea0SLionel Sambuc} mech_anonymous; 155*ebfedea0SLionel Sambuc 156*ebfedea0SLionel Sambuc 157*ebfedea0SLionel Sambuc4. Expected usage 158*ebfedea0SLionel Sambuc 159*ebfedea0SLionel SambucBelow is presented example and expected usage of the library. 160*ebfedea0SLionel Sambuc 161*ebfedea0SLionel Sambuc/* creating context */ 162*ebfedea0SLionel Sambuc... 163*ebfedea0SLionel Sambucctx = saslc_init("example"); 164*ebfedea0SLionel Sambuc 165*ebfedea0SLionel Sambucif ( ctx == NULL ) { 166*ebfedea0SLionel Sambuc //error handler 167*ebfedea0SLionel Sambuc} 168*ebfedea0SLionel Sambuc... 169*ebfedea0SLionel Sambuc 170*ebfedea0SLionel Sambuc 171*ebfedea0SLionel Sambuc/* session */ 172*ebfedea0SLionel Sambucsess = saslc_sess_init(ctx, "PLAIN,ANONYMOUS"); 173*ebfedea0SLionel Sambuc 174*ebfedea0SLionel Sambucif ( sess == NULL ) { 175*ebfedea0SLionel Sambuc //error handler 176*ebfedea0SLionel Sambuc} 177*ebfedea0SLionel Sambuc 178*ebfedea0SLionel Sambucif ( strcmp(saslc_sess_strmech(sess),"PLAIN") == 0 ) { 179*ebfedea0SLionel Sambuc saslc_sess_setprop(sess, "USERID", "foo"); 180*ebfedea0SLionel Sambuc saslc_sess_setprop(sess, "PASSWORD", "bar"); 181*ebfedea0SLionel Sambuc} else if ( strcmp(saslc_sess_strmech(sess),"ANONYMOUS") == 0 ) { 182*ebfedea0SLionel Sambuc saslc_sess_setprop(sess, "TOKEN", "foo@bar.com"); 183*ebfedea0SLionel Sambuc} 184*ebfedea0SLionel Sambuc 185*ebfedea0SLionel Sambuc// sending auth 186*ebfedea0SLionel Sambuc// proto read 187*ebfedea0SLionel Sambuc// parse 188*ebfedea0SLionel Sambuc 189*ebfedea0SLionel Sambucwhile ( (last = sasl_sess_cont(sess, in, inlen, out, outlen)) >= 0 ) { 190*ebfedea0SLionel Sambuc // proto send 191*ebfedea0SLionel Sambuc // proto read 192*ebfedea0SLionel Sambuc // parse 193*ebfedea0SLionel Sambuc 194*ebfedea0SLionel Sambuc if ( last == 0 ) 195*ebfedea0SLionel Sambuc break; 196*ebfedea0SLionel Sambuc} 197*ebfedea0SLionel Sambuc 198*ebfedea0SLionel Sambucif ( last == 0 ) { 199*ebfedea0SLionel Sambuc // yay! 200*ebfedea0SLionel Sambuc} else { 201*ebfedea0SLionel Sambuc // error handler 202*ebfedea0SLionel Sambuc} 203*ebfedea0SLionel Sambuc 204*ebfedea0SLionel Sambuc... 205*ebfedea0SLionel Sambuc/* destroying session and context */ 206*ebfedea0SLionel Sambucsaslc_sess_end(sess); 207*ebfedea0SLionel Sambucsaslc_end(ctx); 208*ebfedea0SLionel Sambuc... 209*ebfedea0SLionel Sambuc 210*ebfedea0SLionel Sambucvim:tw=79:spell:spelllang=en 211