#define KPOP_SERVICE "kpop"
#endif
-#ifdef GSSAPI
-# ifdef HAVE_GSSAPI_H
-# include <gssapi.h>
-# else
-# include <gssapi/gssapi.h>
-# endif
-#define GSSAPI_SERVICE "pop"
-static int pop_auth (/* popserver server, char *user,
- char *host, int flags */);
-static void gen_gss_error (/* char *msg, OM_uint32 major, OM_uint32 minor */);
-struct _pop_gssapi
-{
- int gss_flags; /* encryption? integrity protection? */
- OM_uint32 max_size; /* max size we can send the server */
- gss_ctx_id_t gss_context; /* the security context */
-};
-#define GSSAPI_NOPROT 0x01
-#define GSSAPI_INTEGRITY 0x02
-#define GSSAPI_PRIVACY 0x04
-#define GSSAPI_NEEDWRAP (GSSAPI_INTEGRITY|GSSAPI_PRIVACY)
-#define GSSAPI_PROTECTION (GSSAPI_NOPROT|GSSAPI_INTEGRITY|GSSAPI_PRIVACY)
-#define GSSAPI_RCVBUF 1024
-#define GSSAPI_SVC_TYPE {10, "\052\206\110\206\367\022\001\002\001\004"}
-#define Gssapi(data) ((struct _pop_gssapi *) (data))
-
-static int b64_decode (/* char *enc, gss_buffer_t dec */);
-static int b64_encode (/* gss_buffer_t dec, char **enc */);
-#define B64_SUCCESS 0
-#define B64_BADPARAM 1
-#define B64_BADCHAR 2
-#define B64_BADPAD 3
-#define B64_BADLEN 4
-#define B64_NOMEM 5
-static char *b64_error[] =
-{
- "Success",
- "Bad parameters",
- "Bad characters in encoding",
- "Bad padding in encoding",
- "Bad length",
- "Out of memory"
-};
-
-/*
- * This function is only needed if you are using the GSSAPI protection
- * mechanisms; it keeps trying until it has read the requested number
- * bytes from the passed-in fd.
- */
-static int fullread (/* int fd, char *buf, int nbytes */);
-#endif /* GSSAPI */
-
char pop_error[ERROR_MAX];
int pop_debug = 0;
}
/* Determine the password */
-#if defined(KERBEROS) || defined(GSSAPI)
-# ifdef KERBEROS
-# define NO_KERBEROS POP_NO_KERBEROS
-# else
-# define NO_KERBEROS 0
-# endif /* KERBEROS */
-
-# ifdef GSSAPI
-# define NO_GSSAPI POP_NO_GSSAPI
-# else
-# define NO_GSSAPI 0
-# endif /* GSSAPI */
-
-# define DONT_NEED_PASSWORD (! (flags & (NO_KERBEROS | NO_GSSAPI)))
+#ifdef KERBEROS
+#define DONT_NEED_PASSWORD (! (flags & POP_NO_KERBEROS))
#else
-# define DONT_NEED_PASSWORD 0
+#define DONT_NEED_PASSWORD 0
#endif
if ((! password) && (! DONT_NEED_PASSWORD))
}
}
if (password)
- flags |= POP_NO_KERBEROS | (!(flags & POP_NO_NOPROT) ? POP_NO_GSSAPI : 0);
+ flags |= POP_NO_KERBEROS;
else
password = username;
server->buffer_size = GETLINE_MIN;
server->in_multi = 0;
server->trash_started = 0;
- server->extra = 0;
if (getok (server))
return (0);
-#ifdef GSSAPI
- /*
- * unless forbidden to use GSSAPI, try the GSSAPI AUTH mechanism..first.
- */
- pop_error[0] = '\0'; /* so we can detect errors later... */
- if (! (flags & POP_NO_GSSAPI))
- {
- int ret;
-
- ret = pop_auth (server, username, host, flags);
- if (ret == 0)
- {
- return (server);
- }
- else if (ret == -2)
- {
- pop_close (server);
- return (0);
- }
- }
-#endif /* GSSAPI */
- /*
- * POP_NO_NOPROT is used in the case that we want protection; if
- * the authentication negotiation failed, then we want to fail now.
- */
- if ((flags & POP_NO_NOPROT))
- {
- pop_close (server);
-#ifdef GSSAPI
- if (pop_error[0] == '\0')
-#endif
- strcpy (pop_error, "Unable to provide protection");
- return (0);
- }
-
/*
* I really shouldn't use the pop_error variable like this, but....
*/
if (server->buffer)
free (server->buffer);
-#ifdef GSSAPI
- if (server->extra)
- {
- OM_uint32 minor;
-
- if (Gssapi (server->extra)->gss_context != GSS_C_NO_CONTEXT)
- gss_delete_sec_context (&minor, &(Gssapi (server->extra)->gss_context),
- GSS_C_NO_BUFFER);
- free ((char *) server->extra);
- }
-#endif /* GSSAPI */
free ((char *) server);
return (ret);
while (1)
{
-#ifdef GSSAPI
- /*
- * We might be playing with a protected connection. If we are, then
- * we need to first read a chunk of ciphertext from the server,
- * unwrap it, and stuff it into the buffer.
- */
- if (server->extra &&
- ((Gssapi (server->extra)->gss_flags) & GSSAPI_NEEDWRAP))
+ /* There's a "- 1" here to leave room for the null that we put
+ at the end of the read data below. We put the null there so
+ that find_crlf knows where to stop when we call it. */
+ if (server->data == server->buffer_size - 1)
{
- char rcvbuf[GSSAPI_RCVBUF];
- OM_uint32 major, minor, length;
- gss_buffer_desc in_tok, out_tok;
- struct _pop_gssapi *gss_data = Gssapi (server->extra);
-
- ret = fullread (server->file, (char *) &length, sizeof (length));
-
- if (ret == sizeof (length))
+ server->buffer_size += GETLINE_INCR;
+ server->buffer = (char *)realloc (server->buffer, server->buffer_size);
+ if (! server->buffer)
{
- in_tok.length = ntohl (length);
-
- if (in_tok.length <= GSSAPI_RCVBUF)
- {
- ret = fullread (server->file, rcvbuf, in_tok.length);
-
- if (ret == in_tok.length)
- {
- in_tok.value = (void *) rcvbuf;
-
- major = gss_unwrap (&minor, gss_data->gss_context,
- &in_tok, &out_tok, 0, 0);
-
- if (major != GSS_S_COMPLETE)
- {
- pop_trash (server);
- gen_gss_error ("unwrapping", major, minor);
- return (-1);
- }
-
- while (server->data + out_tok.length >=
- server->buffer_size - 1)
- server->buffer_size += GETLINE_INCR;
-
- server->buffer = (char *)realloc (server->buffer,
- server->buffer_size);
-
- if (! server->buffer)
- {
- gss_release_buffer (&minor, &out_tok);
- pop_trash (server);
- strcpy (pop_error, "Out of memory in pop_getline");
- return (-1);
- }
-
- bcopy (out_tok.value, server->buffer + server->data,
- out_tok.length);
-
- ret = out_tok.length;
-
- gss_release_buffer (&minor, &out_tok);
- }
- else
- ret = 0; /* force detection of unexpected EOF */
- }
- else
- {
- pop_trash (server);
- strcpy (pop_error, "Token from server too long in pop_getline");
- return (-1);
- }
- }
- else
- ret = 0; /* force detection of unexpected EOF */
- }
- else
- {
-#endif /* GSSAPI */
- /* There's a "- 1" here to leave room for the null that we put
- at the end of the read data below. We put the null there so
- that find_crlf knows where to stop when we call it. */
- if (server->data == server->buffer_size - 1)
- {
- server->buffer_size += GETLINE_INCR;
- server->buffer = (char *)realloc (server->buffer,
- server->buffer_size);
- if (! server->buffer)
- {
- strcpy (pop_error, "Out of memory in pop_getline");
- pop_trash (server);
- return (-1);
- }
+ strcpy (pop_error, "Out of memory in pop_getline");
+ pop_trash (server);
+ return (-1);
}
- ret = RECV (server->file, server->buffer + server->data,
- server->buffer_size - server->data - 1, 0);
-#ifdef GSSAPI
}
-#endif /* GSSAPI */
+ ret = RECV (server->file, server->buffer + server->data,
+ server->buffer_size - server->data - 1, 0);
if (ret < 0)
{
strcpy (pop_error, GETLINE_ERROR);
/* NOTREACHED */
}
-#ifdef GSSAPI
-/*
- * Function: fullread
- *
- * Purpose: Just like read, but keeps trying until the specified number
- * number of bytes has been read into the buffer. This function is
- * only needed if you are using the GSSAPI protection mechanisms.
- *
- * Return value: Same as read. Pop_error is not set.
- */
-static int
-fullread (fd, buf, nbytes)
- int fd;
- char *buf;
- int nbytes;
-{
- char *cp;
- int ret;
-
- cp = buf;
-
- while (nbytes > 0 && (ret = RECV (fd, cp, nbytes, 0)) > 0)
- {
- cp += ret;
- nbytes -= ret;
- }
-
- return (ret);
-}
-#endif /* GSSAPI */
-
/*
* Function: sendline
*
#define SENDLINE_ERROR "Error writing to POP server: "
int ret;
-#ifdef GSSAPI
- /*
- * We might be playing with a protected connection. If we are, then we
- * need to build our full plaintext, parse it into chunks small enough
- * for the server to swallow, wrap each one, and send it over the net as
- * specified by the RFC.
- */
- if (server->extra && ((Gssapi (server->extra)->gss_flags) & GSSAPI_NEEDWRAP))
- {
- char *sendbuf, *ptr;
- OM_uint32 major, minor, length;
- gss_buffer_desc in_tok, out_tok;
- int len = 0, tot_len;
- struct _pop_gssapi *gss_data = Gssapi (server->extra);
-
- sendbuf = malloc (strlen (line) + 3);
-
- if (! sendbuf)
- {
- pop_trash (server);
- strcpy (pop_error, "Out of memory in sendline");
- return (-1);
- }
-
- tot_len = sprintf (sendbuf, "%s\r\n", line);
-
- for (ptr = sendbuf; tot_len > 0; tot_len -= len, ptr += len)
- {
- len = ((tot_len > gss_data->max_size) ?
- gss_data->max_size : tot_len);
-
- in_tok.value = (void *) ptr;
- in_tok.length = len;
-
- major = gss_wrap (&minor, gss_data->gss_context,
- (gss_data->gss_flags & GSSAPI_PRIVACY) ? 1 : 0,
- GSS_C_QOP_DEFAULT, &in_tok, 0, &out_tok);
-
- if (major != GSS_S_COMPLETE)
- {
- free (sendbuf);
- pop_trash (server);
- gen_gss_error ("wrapping", major, minor);
- return (-1);
- }
-
- /*
- * "Once the protection mechanism is in effect, the stream of
- * command and response octets is processed into buffers of
- * ciphertext. Each buffer is transferred over the connection
- * as a stream of octets prepended with a four octet field in
- * network byte order that represents the length of the
- * following data." - RFC 1734, section 2
- */
- length = htonl (out_tok.length);
- ret = fullwrite (server->file, (char *) &length, sizeof (length));
- if (ret == sizeof (length))
- {
- ret = fullwrite (server->file, (char *) out_tok.value,
- out_tok.length);
- }
-
- gss_release_buffer (&minor, &out_tok);
-
- if (ret < 0)
- break;
- }
-
- free (sendbuf);
+ ret = fullwrite (server->file, line, strlen (line));
+ if (ret >= 0)
+ { /* 0 indicates that a blank line was written */
+ ret = fullwrite (server->file, "\r\n", 2);
}
- else
- {
-#endif /* GSSAPI */
- ret = fullwrite (server->file, line, strlen (line));
- if (ret >= 0)
- { /* 0 indicates that a blank line was written */
- ret = fullwrite (server->file, "\r\n", 2);
- }
-#ifdef GSSAPI
- }
-#endif /* GSSAPI */
if (ret < 0)
{
free (server->buffer);
server->buffer = 0;
}
-#ifdef GSSAPI
- if (server->extra)
- {
- OM_uint32 minor;
-
- if (Gssapi (server->extra)->gss_context != GSS_C_NO_CONTEXT)
- gss_delete_sec_context (&minor,
- &(Gssapi (server->extra)->gss_context),
- GSS_C_NO_BUFFER);
- free ((char *) server->extra);
- server->extra = 0;
- }
-#endif /* GSSAPI */
}
#ifdef WINDOWSNT
#endif
}
-#ifdef GSSAPI
-/*
- * Function: pop_auth
- *
- * Purpose: To perform a GSSAPI authentication handshake with a POP server.
- * If the negotiation is successful, it will return 0; otherwise, it
- * will fill in pop_error with the error message and return either -1,
- * indicating a potentially recoverable error, or -2, indicating an
- * unrecoverable error.
- *
- * Side effects: The server may choose to close the connection if the
- * handshake fails. The connection will be trashed if the error is
- * unrecoverable.
- */
-static int
-pop_auth (server, username, host, flags)
- popserver server;
- char *username, *host;
- int flags;
-{
- int gss_flags, ret;
- char *fromserver;
- OM_uint32 max_size, t_flags;
- gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
- gss_buffer_desc in_tok, out_tok;
- gss_name_t svc_name;
- OM_uint32 major, minor, t_minor;
-
- /* calculate usable protection mechanisms */
- gss_flags = (GSSAPI_PROTECTION &
- ~(((flags & POP_NO_NOPROT) ? GSSAPI_NOPROT : 0) |
- ((flags & POP_NO_INTEG) ? GSSAPI_INTEGRITY : 0) |
- ((flags & POP_NO_ENCRYPT) ? GSSAPI_PRIVACY : 0)));
-
- if (gss_flags == 0)
- {
- strcpy (pop_error, "Unable to provide selected protection level");
- return (-1);
- }
-
- /* import service name of pop server */
- in_tok.value = (void *) malloc (strlen (host) + sizeof (GSSAPI_SERVICE) + 2);
-
- if (! in_tok.value)
- {
- strcpy (pop_error, "Out of memory in pop_auth");
- return (-1);
- }
-
- sprintf ((char *) in_tok.value, "%s@%s", GSSAPI_SERVICE, host);
- in_tok.length = strlen ((char *) in_tok.value);
-
- {
- gss_OID_desc svc_name_oid = GSSAPI_SVC_TYPE;
-
- major = gss_import_name (&minor, &in_tok, &svc_name_oid, &svc_name);
- }
-
- free ((char *) in_tok.value);
-
- if (major != GSS_S_COMPLETE)
- {
- gen_gss_error ("parsing name", major, minor);
- return (-1);
- }
-
- /* begin GSSAPI authentication handshake */
- if (sendline (server, "AUTH GSSAPI") || (pop_getline (server, &fromserver) < 0))
- {
- gss_release_name (&t_minor, &svc_name);
- return (-1);
- }
-
- do
- {
- /* sanity-check server response */
- if (strncmp (fromserver, "+ ", 2))
- {
- gss_release_name (&t_minor, &svc_name);
- if (gss_context != GSS_C_NO_CONTEXT)
- gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER);
- if (0 == strncmp (fromserver, "-ERR", 4))
- {
- strncpy (pop_error, fromserver, ERROR_MAX);
- return (-1);
- }
- else
- {
- pop_trash (server);
- strcpy (pop_error,
- "Unexpected response from POP server in pop_auth");
- return (-2);
- }
- }
-
- if (strlen (fromserver) > 2)
- {
- /* base 64 decode the response... */
- ret = b64_decode (fromserver + 2, &in_tok);
- if (ret != B64_SUCCESS)
- {
- gss_release_name (&t_minor, &svc_name);
- if (gss_context != GSS_C_NO_CONTEXT)
- gss_delete_sec_context (&t_minor, &gss_context,
- GSS_C_NO_BUFFER);
- sendline (server, "*");
- strcpy (pop_error, b64_error[ret]);
- return (-1);
- }
- }
- else
- {
- in_tok.length = 0;
- in_tok.value = 0;
- }
-
- /* call init_sec_context */
- major = gss_init_sec_context (&minor, GSS_C_NO_CREDENTIAL, &gss_context,
- svc_name, GSS_C_NULL_OID,
- GSS_C_MUTUAL_FLAG, 0,
- GSS_C_NO_CHANNEL_BINDINGS,
- in_tok.length ? & in_tok : GSS_C_NO_BUFFER,
- 0, &out_tok, 0, 0);
-
- if (in_tok.length != 0)
- free ((char *) in_tok.value);
-
- /* check for error */
- if (GSS_ERROR (major))
- {
- gss_release_name (&t_minor, &svc_name);
- if (gss_context != GSS_C_NO_CONTEXT)
- gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER);
- sendline (server, "*");
- gen_gss_error ("in init_sec_context", major, minor);
- return (-1);
- }
-
- if (out_tok.length != 0)
- {
- /* base 64 encode output token, if any */
- ret = b64_encode (&out_tok, &fromserver);
-
- gss_release_buffer (&t_minor, &out_tok);
-
- if (ret != B64_SUCCESS)
- {
- gss_release_name (&t_minor, &svc_name);
- if (gss_context != GSS_C_NO_CONTEXT)
- gss_delete_sec_context (&t_minor, &gss_context,
- GSS_C_NO_BUFFER);
- sendline (server, "*");
- strcpy (pop_error, b64_error[ret]);
- return (-1);
- }
-
- /* send output token... */
- ret = sendline (server, fromserver);
-
- free (fromserver);
- }
- else
- /* empty output token... */
- ret = sendline (server, "");
-
- /* get next token from server */
- if (ret || (pop_getline (server, &fromserver) < 0))
- {
- gss_release_name (&t_minor, &svc_name);
- if (gss_context != GSS_C_NO_CONTEXT)
- gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER);
- return (-1);
- }
- } while ((major & GSS_S_CONTINUE_NEEDED));
-
- /* release name... */
- gss_release_name (&t_minor, &svc_name);
-
- /* get final response from server */
- if (strncmp (fromserver, "+ ", 2))
- {
- gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER);
- if (0 == strncmp (fromserver, "-ERR", 4))
- {
- strncpy (pop_error, fromserver, ERROR_MAX);
- return (-1);
- }
- else
- {
- pop_trash (server);
- strcpy (pop_error,
- "Unexpected response from POP server in pop_auth");
- return (-2);
- }
- }
-
- /* base 64 decode... */
- ret = b64_decode (fromserver + 2, &in_tok);
- if (ret != B64_SUCCESS)
- {
- gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER);
- sendline (server, "*");
- strcpy (pop_error, b64_error[ret]);
- return (-1);
- }
-
- /* unwrap... */
- major = gss_unwrap (&minor, gss_context, &in_tok, &out_tok, 0, 0);
-
- free ((char *) in_tok.value);
-
- if (major != GSS_S_COMPLETE || out_tok.length != sizeof (t_flags))
- {
- if (out_tok.length != 0)
- gss_release_buffer (&t_minor, &out_tok);
- gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER);
- sendline (server, "*");
- gen_gss_error ("in gss_unwrap", major, minor);
- return (-1);
- }
-
- /* get and check flags/size */
- bcopy ((void *) out_tok.value, (void *) &t_flags, sizeof (t_flags));
-
- gss_release_buffer (&t_minor, &out_tok);
-
- max_size = ntohl (t_flags);
-
- t_flags = ((max_size & 0xFF000000) >> 24) & gss_flags;
- max_size &= 0x00FFFFFF;
-
- if ((t_flags & GSSAPI_PRIVACY))
- gss_flags = GSSAPI_PRIVACY;
-
- else if ((t_flags & GSSAPI_INTEGRITY))
- gss_flags = GSSAPI_INTEGRITY;
-
- else if ((t_flags & GSSAPI_NOPROT))
- gss_flags = GSSAPI_NOPROT;
-
- else
- {
- gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER);
- sendline (server, "*");
- strcpy (pop_error, "Server does not provide selected protection level");
- return (-1);
- }
-
- if (max_size == 0)
- {
- gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER);
- sendline (server, "*");
- strcpy (pop_error, "Bad server max length");
- return (-1);
- }
-
- if ((gss_flags & GSSAPI_NEEDWRAP))
- {
- major = gss_wrap_size_limit (&t_minor, gss_context,
- (gss_flags & GSSAPI_PRIVACY) ? 1 : 0,
- GSS_C_QOP_DEFAULT,
- (max_size < GSSAPI_RCVBUF) ? max_size :
- GSSAPI_RCVBUF, &max_size);
- if (major != GSS_S_COMPLETE)
- {
- gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER);
- sendline (server, "*");
- gen_gss_error ("getting max size", major, minor);
- return (-1);
- }
- }
-
- /* generate return flags */
- {
- OM_uint32 tmp;
-
- tmp = (((gss_flags << 24) & 0xFF000000) | (GSSAPI_RCVBUF & 0x00FFFFFF));
- t_flags = ntohl (tmp);
- }
-
- in_tok.length = sizeof (t_flags) + strlen (username);
- in_tok.value = (void *) malloc (in_tok.length);
-
- if (! in_tok.value)
- {
- gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER);
- sendline (server, "*");
- strcpy (pop_error, "Out of memory in pop_auth");
- return (-1);
- }
-
- bcopy ((void *) &t_flags, in_tok.value, sizeof (t_flags));
- bcopy ((void *) username,
- (void *) (((char *) in_tok.value) + sizeof (t_flags)),
- in_tok.length - sizeof (t_flags));
-
- /* wrap result */
- major = gss_wrap (&minor, gss_context, 0, GSS_C_QOP_DEFAULT,
- &in_tok, 0, &out_tok);
-
- free ((char *) in_tok.value);
-
- if (major != GSS_S_COMPLETE || out_tok.length == 0)
- {
- if (out_tok.length != 0)
- gss_release_buffer (&t_minor, &out_tok);
- gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER);
- sendline (server, "*");
- gen_gss_error ("in gss_wrap", major, minor);
- return (-1);
- }
-
- /* base 64 encode... */
- ret = b64_encode (&out_tok, &fromserver);
-
- gss_release_buffer (&t_minor, &out_tok);
-
- if (ret != B64_SUCCESS)
- {
- gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER);
- sendline (server, "*");
- strcpy (pop_error, b64_error[ret]);
- return (-1);
- }
-
- /* send to server */
- ret = sendline (server, fromserver);
-
- free (fromserver);
-
- /* see if the server likes me... */
- if (ret || getok (server))
- {
- gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER);
- return (-1);
- }
-
- /* stash context */
- {
- struct _pop_gssapi *gss_data;
-
- gss_data = (struct _pop_gssapi *) malloc (sizeof (struct _pop_gssapi));
-
- if (! gss_data)
- {
- pop_trash (server);
- gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER);
- strcpy (pop_error, "Out of memory in pop_auth");
- return (-2);
- }
-
- gss_data->gss_flags = gss_flags;
- gss_data->max_size = max_size;
- gss_data->gss_context = gss_context;
-
- server->extra = gss_data;
- }
-
- return (0);
-}
-
-/*
- * Add as much error text to pop_error as will fit, but only put complete
- * messages
- */
-static void
-gen_gss_error (msg, major, minor)
- char *msg;
- OM_uint32 major, minor;
-{
- char *p = pop_error, *t, *saved;
- int max = ERROR_MAX - 1; /* for \0 */
- OM_uint32 t_minor, msg_ctx = 0;
- gss_buffer_desc gss_msg;
-
- while (*msg && max)
- {
- *p++ = *msg++;
- max--;
- }
-
- if (max >= 2)
- {
- saved = p;
- *p++ = ':';
- *p++ = ' ';
- max -= 2;
- }
- else
- {
- *p = '\0';
- return;
- }
-
- do
- {
- gss_display_status (&t_minor, major, GSS_C_GSS_CODE, GSS_C_NO_OID,
- &msg_ctx, &gss_msg);
- for (t = (char *) gss_msg.value; *t && max; max--)
- {
- *p++ = *t++;
- }
- gss_release_buffer (&t_minor, &gss_msg);
- if (max == 0)
- {
- *saved = '\0';
- return;
- }
- } while (msg_ctx);
-
- saved = p;
-
- do
- {
- gss_display_status (&t_minor, minor, GSS_C_MECH_CODE, GSS_C_NO_OID,
- &msg_ctx, &gss_msg);
- for (t = (char *) gss_msg.value; *t && max; max--)
- {
- *p++ = *t++;
- }
- gss_release_buffer (&t_minor, &gss_msg);
- if (max == 0)
- {
- *saved = '\0';
- return;
- }
- } while (msg_ctx);
-
- *p = '\0';
- return;
-}
-
-/*
- * table-based base64 decoding function; takes 4 characters from in and
- * writes from 1 to 3 bytes to out, storing the amount written in len
- */
-static int
-b64_d (in, out, len)
- char *in, *out;
- int *len;
-{
- int decodearray[] =
- {
- 0x3e, -1, -1, -1, 0x3f, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a,
- 0x3b, 0x3c, 0x3d, -1, -1, -1, -1, -1, -1, -1, 0x00, 0x01,
- 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
- 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
- -1, -1, -1, -1, -1, -1, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
- 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33
- };
-
- int d;
-
- if (!in || !out || !len)
- return (B64_BADPARAM);
-
- if (*in < '+' || *in > 'z')
- return (B64_BADCHAR);
-
- d = decodearray[*(in++) - '+'];
- if (d == -1)
- return (B64_BADCHAR);
- *out = d << 2;
-
- if (*in < '+' || *in > 'z')
- return (B64_BADCHAR);
-
- d = decodearray[*(in++) - '+'];
- if (d == -1)
- return (B64_BADCHAR);
- *(out++) |= d >> 4;
- *out = (d & 15) << 4;
-
- if (*in < '+' || *in > 'z')
- return (B64_BADCHAR);
- else if (*in == '=')
- if (*(in + 1) != '=')
- return (B64_BADPAD);
- else
- {
- *len = 1;
- return (B64_SUCCESS);
- }
-
- d = decodearray[*(in++) - '+'];
- if (d == -1)
- return (B64_BADCHAR);
- *(out++) |= d >> 2;
- *out = (d & 3) << 6;
-
- if (*in < '+' || *in > 'z')
- return (B64_BADCHAR);
- else if (*in == '=')
- {
- *len = 2;
- return (B64_SUCCESS);
- }
-
- d = decodearray[*in - '+'];
- if (d == -1)
- return (B64_BADCHAR);
- *out |= d;
-
- *len = 3;
- return (B64_SUCCESS);
-}
-
-/*
- * simple base64 encoding function that takes from 0 to 3 bytes and
- * outputs 4 encoded characters, with appropriate padding
- */
-static int
-b64_e (in, out, len)
- unsigned char *in, *out;
- int len;
-{
- unsigned char codearray[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
- if (!in || !out || len <= 0 || len > 3)
- return (B64_BADPARAM);
-
- *(out++) = codearray[((*in) >> 2)];
-
- if (--len == 0)
- {
- *(out++) = codearray[(((*in) & 3) << 4)];
- *(out++) = '=';
- *out = '=';
- return (B64_SUCCESS);
- }
-
- *(out++) = codearray[(((*in) & 3) << 4) | ((*(in + 1)) >> 4)];
- in++;
-
- if (--len == 0)
- {
- *(out++) = codearray[(((*in) & 15) << 2)];
- *out = '=';
- return (B64_SUCCESS);
- }
-
- *(out++) = codearray[(((*in) & 15) << 2) | ((*(in + 1)) >> 6)];
- *out = codearray[((*(in + 1)) & 63)];
-
- return (B64_SUCCESS);
-}
-
-/*
- * given an input string, generate an output gss_buffer_t containing the
- * decoded data and correct length; works by repeatedly driving b64_d ()
- * over the input string
- */
-static int
-b64_decode (enc, dec)
- char *enc;
- gss_buffer_t dec;
-{
- char *tmp;
- int inlen, outlen = 0, t_len, ret;
-
- if (!enc || !dec)
- return (B64_BADPARAM);
-
- dec->value = 0;
- dec->length = 0;
-
- inlen = strlen (enc);
- if ((inlen % 4))
- return (B64_BADLEN);
-
- dec->value = (void *) (tmp = (char *) malloc ((inlen / 4) * 3));
-
- if (! tmp)
- return (B64_NOMEM);
-
- for (; inlen; inlen -= 4)
- {
- ret = b64_d (enc, tmp, &t_len);
- if (ret != B64_SUCCESS)
- {
- free ((char *) dec->value);
- dec->value = 0;
- return (ret);
- }
- else if (t_len != 3)
- {
- dec->length = outlen + t_len;
- return (B64_SUCCESS);
- }
- else
- {
- enc += 4;
- tmp += t_len;
- outlen += t_len;
- }
- }
-
- dec->length = outlen;
- return (B64_SUCCESS);
-}
-
-/*
- * given a gss_buffer_t, generate an encoded string containing the data.
- * works by repeatedly driving b64_e () over the contents of the buffer_t
- */
-static int
-b64_encode (dec, enc)
- gss_buffer_t dec;
- char **enc;
-{
- unsigned char *tmp, *in;
- int ret, len;
-
- if (!dec || !enc)
- return (B64_BADPARAM);
-
- in = (unsigned char *) dec->value;
- len = dec->length;
- *enc = (char *) (tmp = (unsigned char *) malloc (((len * 4) / 3) + 5));
-
- if (! tmp)
- return (B64_NOMEM);
-
- do
- {
- ret = b64_e (in, tmp, len >= 3 ? 3 : len);
- if (ret != B64_SUCCESS)
- {
- free (*enc);
- *enc = 0;
- return (ret);
- }
- else
- {
- in += 3;
- tmp += 4;
- }
- } while ((len -= 3) > 0);
-
- *tmp = '\0';
-
- return (B64_SUCCESS);
-}
-
-#endif /* GSSAPI */
-
/* Return a pointer to the first CRLF in IN_STRING, which can contain
embedded nulls and has LEN characters in it not including the final
null, or 0 if it does not contain one. */