1.\" $NetBSD: libsaslc.3,v 1.16 2015/07/13 13:57:44 shm Exp $ 2.\" 3.\" Copyright (c) 2010 The NetBSD Foundation, Inc. 4.\" All rights reserved. 5.\" 6.\" This code is derived from software contributed to The NetBSD Foundation 7.\" by Mateusz Kocielski. 8.\" 9.\" Redistribution and use in source and binary forms, with or without 10.\" modification, are permitted provided that the following conditions 11.\" are met: 12.\" 1. Redistributions of source code must retain the above copyright 13.\" notice, this list of conditions and the following disclaimer. 14.\" 2. Redistributions in binary form must reproduce the above copyright 15.\" notice, this list of conditions and the following disclaimer in the 16.\" documentation and/or other materials provided with the distribution. 17.\" 3. All advertising materials mentioning features or use of this software 18.\" must display the following acknowledgement: 19.\" This product includes software developed by the NetBSD 20.\" Foundation, Inc. and its contributors. 21.\" 4. Neither the name of The NetBSD Foundation nor the names of its 22.\" contributors may be used to endorse or promote products derived 23.\" from this software without specific prior written permission. 24.\" 25.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 26.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 29.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35.\" POSSIBILITY OF SUCH DAMAGE. 36.\" 37.Dd May 3, 2015 38.Dt LIBSASLC 3 39.Os 40.Sh NAME 41.Nm libsaslc , 42.Nm saslc.d , 43.Nm saslc_alloc , 44.Nm saslc_end , 45.Nm saslc_init , 46.Nm saslc_sess_init , 47.Nm saslc_sess_end , 48.Nm saslc_sess_getprop , 49.Nm saslc_sess_setprop , 50.Nm saslc_sess_cont , 51.Nm saslc_sess_decode , 52.Nm saslc_sess_encode , 53.Nm saslc_sess_getmech , 54.Nm saslc_sess_strerror , 55.Nm saslc_strerror 56.Nd Simple Authentication and Security Layer client library 57.Sh LIBRARY 58.Lb libsaslc 59.Sh SYNOPSIS 60.In saslc.h 61.Ft saslc_t * 62.Fn saslc_alloc "void" 63.Ft int 64.Fn saslc_end "saslc_t *ctx" 65.Ft int 66.Fn saslc_init "saslc_t *ctx" "const char *appname" "const char *cfgpath" 67.Ft saslc_sess_t * 68.Fn saslc_sess_init "saslc_t *ctx" "const char *mechs" "const char *secopts" 69.Ft void 70.Fn saslc_sess_end "saslc_sess_t *sess" 71.Ft const char * 72.Fn saslc_sess_getprop "saslc_sess_t *sess" "const char *key" 73.Ft int 74.Fn saslc_sess_setprop "saslc_sess_t *sess" "const char *key" \ 75"const char *value" 76.Ft int 77.Fn saslc_sess_cont "saslc_sess_t *sess" "const void *in" "size_t inlen" \ 78"void* *out" "size_t *outlen" 79.Ft ssize_t 80.Fn saslc_sess_decode "saslc_sess_t *sess" "const void *in" "size_t inlen" \ 81"void* *out" "size_t *outlen" 82.Ft ssize_t 83.Fn saslc_sess_encode "saslc_sess_t *sess" "const void *in" "size_t inlen" \ 84"void* *out" "size_t *outlen" 85.Ft const char * 86.Fn saslc_sess_getmech "saslc_sess_t *sess" 87.Ft const char * 88.Fn saslc_sess_strerror "saslc_sess_t *sess" 89.Ft const char * 90.Fn saslc_strerror "saslc_t *ctx" 91.Sh DESCRIPTION 92The 93.Nm libsaslc 94library offers a client interface for the 95Simple Authentication and Security Layer 96.Pq Tn SASL . 97The library is heavily influenced by its use with 98.Xr postfix 1 . 99.Sh FUNCTIONS 100The following functions are available in the library. 101.Bl -tag -width compact 102.It Fn saslc_alloc "" 103The 104.Fn saslc_alloc 105function allocates and returns a new saslc context. 106The context is uninitialized: see 107.Fn saslc_init . 108Returns 109.Dv NULL 110on error. 111.It Fn saslc_end "ctx" 112The 113.Fn saslc_end 114function destroys and deallocate resources used by the context 115.Ar ctx . 116The context shouldn't have any sessions assigned to it. 117Returns 0 on success and \-1 if the context has active sessions and 118cannot be deallocated. 119.It Fn saslc_init "ctx" "appname" "cfgpath" 120The 121.Fn saslc_init 122function initializes the saslc context 123.Ar ctx . 124Based on the application name 125.Ar appname , 126it also parses the configuration files as indicated by 127.Ar cfgpath , 128sets up the context and mechanism dictionaries, and creates mechanism 129list for the context. 130If 131.Ar cfgpath 132is 133.Dv NULL , 134it checks the environment variable 135.Ev SASLC_CONFIG 136for a location and if that is not found it uses the default path 137.Pa /etc/saslc.d . 138Returns 0 on success and \-1 on failure. 139.It Fn saslc_sess_init "ctx" "mechs" "secopts" 140The 141.Fn saslc_sess_init 142function creates new session assigned to the 143.Ar ctx 144context. 145The function chooses the mechanism to use for authentication from the 146.Ar mechs 147list taking into account the requirements from the 148.Ar secopts 149list. 150Both lists may be space or comma delimited. 151The first matching mechanism from the 152.Ar mechs 153list is used. 154See 155.Sx CONFIGURATION 156below for the supported mechanisms. 157The valid security options are 158.Pp 159.Bl -tag -width "nodictionaryxxx" -offset indent -compact 160.It Qo noanonymous Qc 161reject anonymous mechanisms 162.It Qo noplaintext Qc 163reject plaintext mechanisms 164.It Qo nodictionary Qc 165reject mechanisms prone to dictionary attack 166.It Qo noactive Qc 167reject mechanisms prone to active non-dictionary attacks 168.It Qo mutual Qc 169require mutual authentication mechanisms 170.El 171.Pp 172Unknown security options are ignored. 173Returns a session handle or 174.Dv NULL 175on error or no match. 176.It Fn saslc_sess_end "sess" 177The 178.Fn saslc_sess_end 179function ends the sasl session 180.Ar sess . 181It destroys and deallocates all internal resources. 182This does not fail. 183.It Fn saslc_sess_getprop "sess" "key" 184The 185.Fn saslc_sess_getprop 186function gets the property indicated by the 187.Ar key 188from the saslc dictionaries. 189Dictionaries are searched in following order: session 190.Ar sess 191dictionary, 192context dictionary (global configuration), and mechanism dictionary. 193Returns the property value or 194.Dv NULL 195if the property is not found. 196.It Fn saslc_sess_setprop "sess" "key" "value" 197The 198.Fn saslc_sess_setprop 199function sets the property indexed by 200.Ar key 201to the value 202.Ar value 203in the session 204.Ar sess 205dictionary. 206If the property already exists in the session dictionary, then the 207previous value is replaced by the new value. 208If 209.Ar value 210is 211.Dv NULL , 212then any previous value in the session dictionary is removed. 213Returns 0 on success or \-1 on failure. 214.It Fn saslc_sess_cont "sess" "in" "inlen" "out" "outlen" 215The 216.Fn saslc_sess_cont 217function performs one step of the sasl authentication. 218It reads 219.Ar inlen 220bytes of input data 221.Pq from the server 222from the 223.Ar in 224buffer and stores 225.Ar outlen 226bytes of output data in 227.Ar out 228.Pq for the server . 229The user is responsible for freeing memory allocated for 230.Ar out . 231It returns 0 if the authentication process is completed, 1 if another 232step is required, and \-1 on error. 233Note that the completion of authentication process does not mean the 234client is authenticated; that is determined by the server. 235.It Fn saslc_sess_decode "sess" "in" "inlen" "out" "outlen" 236The 237.Fn saslc_sess_encode 238and 239.Fn saslc_sess_decode 240functions are used to provide the integrity 241.Pq Qq auth-int 242and confidentiality 243.Pq Qq auth-conf 244layers for mechanisms that provide them. 245They encode and, respectively, decode 246.Ar inlen 247bytes of data from the 248.Ar in 249buffer using the method negotiated during authentication. 250On error they return \-1. 251Otherwise, they return the number of bytes consumed from 252.Ar in 253and output 254.Ar outlen 255bytes of data in the 256.Ar out 257buffer. 258The user is responsible for freeing memory allocated for 259.Ar out . 260If 261.Ar outlen 262is 0, more data is needed before anything can be output. 263Unused input data is stored internally for use in subsequent calls. 264.Pp 265When decoding, the internal buffers can only be flushed by providing 266the missing packet data and it is an error to call 267.Fn ssalc_sess_decode 268with 269.Ar inlen 270= 0. 271The first call of 272.Fn saslc_sess_decode 273in a session must begin at the start of a packet. 274Subsequent calls need not be aligned on packet boundaries. 275.It Fn saslc_sess_encode "sess" "in" "inlen" "out" "outlen" 276As described above, 277.Fn saslc_sess_encode 278encodes 279.Ar inlen 280bytes of data from the 281.Ar in 282buffer. 283Note that unlike when decoding, 284the internal buffer may be flushed through the encoder 285by calling 286.Fn saslc_sess_encode 287with 288.Ar inlen 289= 0. 290In this case, 291.Fn saslc_sess_encode 292returns the number of bytes that were flushed from the internal buffer. 293.It Fn saslc_sess_getmech "sess" 294The 295.Fn saslc_sess_getmech 296function returns the name of the mechanism used in the session 297.Fa sess . 298The function does not fail. 299.It Fn saslc_sess_strerror "sess" 300The 301.Fn saslc_sess_strerror 302returns the error message associated with the session 303.Fa sess . 304.It Fn saslc_strerror "ctx" 305The 306.Fn saslc_strerror 307function operates as 308.Fn saslc_sess_strerror , 309but instead returns the error message string for the last error in the context 310.Fa ctx . 311Neither function will ever return 312.Dv NULL . 313.El 314.Sh CONFIGURATION 315The library uses three types of dictionaries: context (or global), 316session, and mechanism, and they are searched in that order by 317.Fn saslc_getprop 318and the first matching entry is taken. 319The context and mechanism dictionaries are loaded from configuration 320files, while the session dictionary is loaded by the caller via 321.Fn saslc_setprop . 322.Pp 323The configuration file 324.Pa <cfgpath>/<appname>/saslc.conf 325is used for the context configuration. 326The 327.Pa <cfgpath>/<appname>/mech/<mechanism>.conf 328file is used for the mechanism configuration. 329The 330.Pa <cfgpath> 331is 332.Pa /etc/saslc.d 333by default, but this may be overridden by the environment variable 334.Ev SASLC_CONFIG , 335which in turn may be overridden by 336.Fn saslc_init . 337The 338.Pa <appname> 339is 340.Pa saslc 341by default, but may also be overridden by 342.Fn saslc_init . 343Finally, the 344.Pa <mechanism> 345is the mechanism in use by the session as returned by 346.Fn saslc_sess_getmech . 347Note that this name is case sensitive. 348The currently supported mechanisms are 349.Bl -tag -width DIGEST-MD5 -offset indent 350.It ANONYMOUS 351See RFC 2245 and RFC 4505. 352.It CRAM-MD5 353See RFC 2195. 354.It DIGEST-MD5 355See RFC 2831. 356.It EXTERNAL 357See RFC 2222 section 7.4 and RFC 4422 appendix A. 358.It GSSAPI 359See RFC 2222 section 7.2 and RFC 4752. 360This requires GSS, Heimdal, or MIT Kerberos. 361.It LOGIN 362Non-standard, but common. 363.It PLAIN 364See RFC 2595 and RFC 4616. 365.El 366.Pp 367If any of the mechanism files are missing they are silently ignored, 368unless debugging is enabled. 369.Pp 370The configuration files consists of lines of the form: 371.Bd -literal -offset indent 372\fB#\fP comment line 373.Ao key Ac \~\~ Ao value Ac \~\~ Bo \fB#\fP comment Bc 374.Ed 375.Pp 376The 377.Aq key 378is a string beginning with an alpha character 379.Pq Xr isalpha 3 380followed by any number of alpha numeric 381.Pq Xr isalnum 3 382or underscore 383.Sq _ 384characters; this is case sensitive. 385The 386.Aq value 387is a number or a quoted string. 388More than one 389.Aq key 390and 391.Aq value 392pair may occur on a single line, but they may not be broken across 393lines. 394A 395.Sq \fB#\fP 396character 397.Pq outside a quoted string 398indicates that the rest of the line is a comment. 399.Pp 400NOTE: Currently, no escaping is supported in strings, so they may not 401contain quotes. 402Numbers must be between 0 and 403.Dv LLONG_MAX , 404inclusive. 405Any base supported by 406.Xr strtoll 3 407is allowed. 408.Sh PROPERTIES 409Most of the control of the library 410behavior is done via setting various properties in the context or 411mechanism dictionaries via the configuration files or in the session 412dictionary with 413.Fn saslc_setprop . 414The following properties are currently used, as defined in 415.Pa saslc.h : 416.Bl -tag -width indent 417.It SASLC_PROP_AUTHCID Po Qo AUTHCID Qc Pc 418The authentication name 419.Pq or username 420to authenticate with. 421Used by all mechanisms except EXTERNAL. 422.It SASLC_PROP_AUTHZID Po Qo AUTHZID Qc Pc 423The authorization string to use. 424By default, this string is empty. 425Used by the DIGEST-MD5, EXTERNAL, and PLAIN mechanisms. 426.It SASLC_PROP_BASE64IO Po Qo BASE64IO Qc Pc 427If true ("true", "yes", or nonzero), then input and output strings are 428base64 encoded. 429Any other value is false and the input and output strings are not 430base64 encoded. 431By default, this is assumed true. 432Used by all mechanisms. 433.It SASLC_PROP_CIPHERMASK Po Qo CIPHERMASK Qc Pc 434The mask of ciphers to use with the DIGEST-MD5 mechanism when using 435the 436.Qq auth-conf 437QOP. 438By default all supported ciphers are used, but they may be limited by 439a comma delimited list of cipher names. 440The recognized cipher names for DIGEST-MD5 are: 441.Pp 442.Bl -tag -offset indent -compact 443.It Li "3des" 444Triple-DES Cipher in CBC "two keys" mode with 112 bit key 445.It Li "aes" 446AES Cipher in CBC mode with 128 bit key 447.It Li "des" 448DES Cipher in CBC mode with 56 bit key 449.It Li "rc4" 450RC4 Cipher with 128 bit key 451.It Li "rc4-40" 452RC4 Cipher with 40 bit key 453.It Li "rc4-56" 454RC4 Cipher with 56 bit key 455.El 456.Pp 457The default value is 458.Qq des,3des,rc4,rc4_40,rc4_56,aes . 459.Po 460Note that 461.Qq aes 462is not part of the official standard. 463.Pc 464Used by the DIGEST-MD5 mechanism. 465.It SASLC_PROP_DEBUG Po Qo DEBUG Qc Pc 466If true, then enable debug messages. 467This is implemented as a global variable so it will affect all 468sessions. 469If set via 470.Fn saslc_sess_setprop , 471it should be set before the first call to 472.Fn saslc_sess_cont . 473.Po 474Also see the environment variable 475.Ev SASLC_ENV_DEBUG 476in the 477.Sx ENVIRONMENT 478section below. 479.Pc 480.It SASLC_PROP_HOSTNAME Po Qo HOSTNAME Qc Pc 481The fully qualified domain name of the server host. 482Used by the DIGEST-MD5 and GSSAPI mechanisms. 483.It SASLC_PROP_MAXBUF Po Qo MAXBUF Qc Pc 484The size of the decode buffer. 485This info is sent to the server so that it doesn't send packets that 486won't fit in the decode buffer when decoded. 487Used by the DIGEST-MD5 and GSSAPI mechanisms. 488.It SASLC_PROP_PASSWD Po Qo PASSWD Qc Pc 489The password to authenticate with. 490Used by the CRAM-MD5, DIGEST-MD5, LOGIN, and PLAIN mechanisms. 491.It SASLC_PROP_QOPMASK Po Qo QOPMASK Qc Pc 492The mask of QOP (quality of protection) to use with the DIGEST-MD5 493and GSSAPI mechanisms. 494By default all supported QOP values are allowed, but they may be 495limited by a comma delimited list of QOP values. 496The recognized QOP values are: 497.Pp 498.Bl -tag -offset indent -compact 499.It Li "auth" 500authentication only 501.It Li "auth-int" 502authentication with integrity 503.It Li "auth-conf" 504authentication with confidentiality 505.El 506.Pp 507so the default value of the mask is 508.Qq auth,auth-int,auth-conf . 509Used by the DIGEST-MD5 and GSSAPI mechanisms. 510.It SASLC_PROP_REALM Po Qo REALM Qc Pc 511A comma delimited list of possible realms to use for authentication. 512The format of each element in the list is 513.Qq Oo Ao hostname Ac : Oc Ns Ao realm Ac . 514The user specified realm is the first realm in the list with a 515matching hostname or, if none is found, the first realm in the list 516with no hostname. 517If the server provides a list of realms, the one matching the user 518specified realm is selected. 519If no match is found or if the user didn't provide a realm, the first 520realm provided by the server is selected. 521If the server doesn't provide any realms, use the user specified realm 522if there is one, or the hostname if not. 523This is useful when the server provides multiple realms or no realm. 524Used by the DIGEST-MD5 mechanism. 525.It SASLC_PROP_SECURITY Po Qo SECURITY Qc Pc 526A comma delimited list of extra security option flags that will be 527.Qo or Qc Ns -ed 528together with those passed to 529.Fn saslc_sess_init . 530Since these flags are used to choose the session mechanism, they are 531only effective if they are in the context configuration file. 532.Po 533See the 534.Sx CONFIGURATION 535section and the 536.Fn saslc_sess_init 537function. 538.Pc 539.It SASLC_PROP_SERVICE Po Qo SERVICE Qc Pc 540The service being used, e.g., smtp, imap, etc. 541Used by the DIGEST-MD5 and GSSAPI mechanisms. 542.It SASLC_PROP_SERVNAME Po Qo SERVNAME Qc Pc 543A comma delimited list of possible service names with elements of the 544form 545.Qq Oo Ao hostname Ac : Oc Ns Ao serv-name Ac 546and with the same rules as for the SASLC_PROP_REALM list. 547This should only be used if the client uses a DNS name for the service 548that is different from the FQDN of the server. 549For example, the service name 550.Em example.com 551might resolve 552.Pq via SRV or MX records 553into a set of other DNS names, one of which, 554.Em mail3.example.com , 555is the FQDN of the server. 556.Po 557See RFC 2831 section 2.1.2 558.Qq serv-name . 559.Pc 560Used by the DIGEST-MD5 mechanism. 561.El 562.Pp 563The defines in 564.Pa saslc.h 565should be used in code, but their values need to be used in the config 566files. 567.Sh ENVIRONMENT 568The following environment variables 569.Pq defined in Pa saslc.h 570affect the behavior of the library: 571.Bl -tag -width indent 572.It Ev SASLC_ENV_CONFIG Po Qo SASLC_CONFIG Qc Pc 573If the environment variable 574.Ev SASLC_CONFIG 575is set it overrides the default configuration file location of 576.Pa /etc/saslc.d . 577This may be overridden by 578.Fn saslc_init . 579.It Ev SASLC_ENV_DEBUG Po Qo SASLC_DEBUG Qc Pc 580If set, turn on debugging messages. 581This turns on debugging as early as possible and is a global setting. 582.El 583.Sh GSSAPI AND KERBEROS 584The following is a minimal 585.Pq Heimdal 586Kerberos 5 setup for use with an smtp server that has been configured 587to support 588.Em SASL 589with the 590.Em GSSAPI 591mechanism. 592It assumes that Kerberos and the smtp server will both run on 593.Em server.my.domain 594and that the client is on 595.Em client.my.domain . 596It also assumes that the smtp server runs as user 597.Em postfix 598and group 599.Em mail , 600and that it is not chrooted. 601.Pp 602On 603.Em server.my.domain 604run the following script as 605.Em root 606and then start the Kerberos server 607.Xr kdc 8 . 608You will be prompted for a master password for Kerberos and a password 609for the 610.Em postfix 611principal. 612.Bd -literal -offset indent 613#/bin/sh 614.Pp 615cat <<- EOF >> /etc/krb5.conf 616[libdefaults] 617 default_realm = MY.DOMAIN 618[realms] 619 MY.DOMAIN = { 620 kdc = server.my.domain 621 admin_servers = server.my.domain 622 } 623[domain_realm] 624 .my.domain = MY.DOMAIN 625EOF 626.Pp 627mkdir /var/heimdal 628chown root:wheel /var/heimdal 629chmod 755 /var/heimdal 630.Pp 631kstash 632kadmin -l init --realm-max-ticket-life=unlimited \\ 633 --realm-max-renewable-life=unlimited \\ 634 MY.DOMAIN 635kadmin -l add --max-ticket-life="1 day" \\ 636 --max-renewable-life="1 week" \\ 637 --expiration-time=never \\ 638 --pw-expiration-time=never \\ 639 --attributes="" \\ 640 postfix 641kadmin -l add --random-key \\ 642 --max-ticket-life="1 day" \\ 643 --max-renewable-life="1 week" \\ 644 --expiration-time=never \\ 645 --pw-expiration-time=never \\ 646 --attributes="" \\ 647 smtp/server.my.domain 648kadmin -l ext -k /etc/krb5.keytab smtp/server.my.domain 649chown root:mail /etc/krb5.keytab 650chmod 640 /etc/krb5.keytab 651.Ed 652.Pp 653Note that the keytab 654.Pa /etc/krb5.keytab 655must be readable by the smtp server or authentication will fail. 656The location of this keytab file may be changed with the environment 657variable 658.Ev KRB5_KTNAME . 659If postfix is the smtp server, note the 660.Em import_environment 661parameter 662.Pq see Xr postconf 5 . 663.Pp 664On 665.Em client.my.domain 666copy the keytab file from 667.Pa server.my.domain:/etc/krb5.keytab 668to 669.Pa /etc/krb5.keytab . 670Setup the 671.Pa /etc/saslc.d 672configuration directory 673.Po see Sx CONFIGURATION 674above 675.Pc . 676Add the line 677.Bd -literal -offset indent 678AUTHCID "postfix" 679.Ed 680.Pp 681to the file 682.Pa /etc/saslc.d/postfix/mech/GSSAPI.conf 683so that the 684.Em postfix 685principal will be used for authentication. 686Enable 687.Em SASL 688in the smtp client. 689Assuming the smtp client is postfix, you will need to add the 690following to the 691.Pa /etc/postfix/main.cf 692file to do this: 693.Bd -literal -offset indent 694smtp_sasl_auth_enable = yes 695smtp_sasl_type = saslc 696smtp_sasl_mechanism_filter = GSSAPI 697relayhost = [server.my.domain]:submission 698.Ed 699.Pp 700Here we have assumed the 701.Em submission 702port is the port the server is listening to. 703Finally, as 704.Em root , 705run the command 706.Bd -literal -offset indent 707su -m postfix -c kinit 708.Ed 709.Pp 710to obtain a ticket for the postfix user with the postfix credential 711and you should be good to go! 712.Sh FILES 713.Bl -tag -width /etc/saslc.d 714.It Pa /etc/saslc.d 715.El 716.Sh EXAMPLES 717The following code fragments illustrate the possible use of the 718functions described above. 719.Bd -literal 720int 721decode_stream(saslc_sess_t *sess, int fdin, int fdout) 722{ 723 uint8_t buf[BUFSIZE]; 724 uint8_t *in; 725 void *out; 726 size_t inlen, outlen; 727 ssize_t n, rval; 728.Pp 729 for (;;) { 730 if ((rval = read(fdin, buf, sizeof(buf))) == \-1) 731 return \-1; 732 if (rval == 0) 733 break; 734 in = buf; 735 inlen = rval; 736 while (inlen > 0) { 737 rval = saslc_sess_decode(sess, in, inlen, &out, 738 &outlen); 739 if (rval == \-1) 740 return \-1; 741 if (outlen > 0) { 742 n = write(fdout, out, outlen); 743 free(out); 744 if (n == \-1) 745 return \-1; 746 } 747 in += rval; 748 inlen -= rval; 749 } 750 } 751 return 0; 752} 753.Pp 754int 755encode_stream(saslc_sess_t *sess, int fdin, int fdout) 756{ 757 uint8_t buf[BUFSIZE]; 758 uint8_t *in; 759 void *out; 760 size_t inlen, outlen; 761 ssize_t n, rval; 762.Pp 763 for (;;) { 764 if ((rval = read(fdin, buf, sizeof(buf))) == \-1) 765 return \-1; 766 if (rval == 0) 767 break; 768 in = buf; 769 inlen = rval; 770 while (inlen > 0) { 771 rval = saslc_sess_encode(sess, in, inlen, &out, 772 &outlen); 773 if (rval == \-1) 774 return \-1; 775 if (outlen > 0) { 776 n = write(fdout, out, outlen); 777 free(out); 778 if (n == \-1) 779 return \-1; 780 } 781 in += rval; 782 inlen -= rval; 783 } 784 } 785 /* flush internal encoder buffer */ 786 if (saslc_sess_encode(sess, NULL, 0, &out, &outlen) == \-1) 787 return \-1; 788 if (outlen > 0) 789 if (write(fdout, out, outlen) == \-1) 790 return \-1; 791 return 0; 792} 793.Ed 794.Sh COMPATIBILITY 795There exist other SASL client library implementations including Cyrus SASL 796(http://asg.web.cmu.edu/sasl/sasl-library.html) and GNU SASL 797(http://www.gnu.org/software/gsasl/). 798.Sh STANDARDS 799RFC 2195, RFC 2222, RFC 2245, RFC 2595, RFC 2831, RFC 4422, RFC 4505, 800RFC 4616, RFC 4752. 801.Sh HISTORY 802The 803.Nm 804library appeared in 805.Nx 6.0 . 806.Sh CAVEATS 807The API was heavily influenced by its use with 808.Xr postfix 1 . 809.Pp 810Currently the ANONYMOUS, LOGIN, PLAIN, CRAM-MD5, DIGEST-MD5, and 811GSSAPI mechanisms have been tested and shown to work for 812authentication with a 813.Xr postfix 1 814SMTP server using the cyrus-sasl library. 815LOGIN, PLAIN, CRAM-MD5, and DIGEST-MD5 have also been tested and shown 816to work with a 817.Xr postfix 1 818SMTP server using a dovecot backend for authentication. 819The DIGEST-MD5 and GSSAPI specs also provide for integrity and 820confidentiality layers via the 821.Fn saslc_sess_encode 822and 823.Fn saslc_sess_decode 824routines, but these have not yet been tested against any servers. 825