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