Example #1
0
/* pgp passwd */
static int pgp_login(void *obj, struct passwd **uam_pwd,
		     char *ibuf, size_t ibuflen,
		     char *rbuf, size_t *rbuflen)
{
    size_t len, i;
    char *name;

    *rbuflen = 0;

    if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, (void *) &name, &i) < 0)
      return AFPERR_PARAM;

    len = (unsigned char) *ibuf++;
    if ( len > i ) {
	return( AFPERR_PARAM );
    }

    memcpy(name, ibuf, len );
    ibuf += len;
    name[ len ] = '\0';
    if ((unsigned long) ibuf & 1) /* padding */
      ++ibuf;

    if (( pgppwd = uam_getname(obj, name, i)) == NULL ) {
      return AFPERR_PARAM;
    }

    LOG(log_info, logtype_uams, "pgp login: %s", name);
    if (uam_checkuser(pgppwd) < 0)
      return AFPERR_NOTAUTH;

    /* get the challenge */
    len = (unsigned char) *ibuf++;
    /* challenge */
    
    /* get the signature. it's always 16 bytes. */
    if (uam_afpserver_option(obj, UAM_OPTION_SIGNATURE, 
			     (void *) &name, NULL) < 0) {
      *rbuflen = 0;
      goto pgp_fail;
    }
    memcpy(rbuf + KEYSIZE, name, KEYSIZE); 

pgp_fail:
    return AFPERR_PARAM;
}
Example #2
0
static int gss_logincont(void *obj,
                         struct passwd **uam_pwd,
                         char *ibuf, size_t ibuflen,
                         char *rbuf, size_t *rbuflen)
{
    struct passwd *pwd = NULL;
    uint16_t login_id;
    char *username;
    uint16_t ticket_len;
    char *p;
    int rblen;
    size_t userlen;
    struct session_info *sinfo;

    /* Apple's AFP 3.1 documentation specifies that this command
     * takes the following format:
     * pad (byte)
     * id returned in LoginExt response (uint16_t)
     * username (format unspecified)
     *   padded, when necessary, to end on an even boundary
     * ticket length (uint16_t)
     * ticket
     */

    /* Observation of AFP clients in the wild indicate that the actual
     * format of this request is as follows:
     * pad (byte) [consumed before login_ext is called]
     * ?? (byte) - always observed to be 0
     * id returned in LoginExt response (uint16_t)
     * username, encoding unspecified, null terminated C string,
     *   padded when the terminating null is an even numbered byte.
     *   The packet is formated such that the username begins on an
     *   odd numbered byte. Eg if the username is 3 characters and the
     *   terminating null makes 4, expect to pad the the result.
     *   The encoding of this string is unknown.
     * ticket length (uint16_t)
     * ticket
     */

    rblen = *rbuflen = 0;

    if (ibuflen < 1 +sizeof(login_id)) {
        LOG_LOGINCONT(log_info, "received incomplete packet");
        return AFPERR_PARAM;
    }
    ibuf++, ibuflen--; /* ?? */

    /* 2 byte ID from LoginExt -- always '00 01' in this implementation */
    memcpy(&login_id, ibuf, sizeof(login_id));
    ibuf += sizeof(login_id), ibuflen -= sizeof(login_id);
    login_id = ntohs(login_id);

    /* get the username buffer from apfd */
    if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, &username, &userlen) < 0)
        return AFPERR_MISC;

    /* get the session_info structure from afpd. We need the session key */
    if (uam_afpserver_option(obj, UAM_OPTION_SESSIONINFO, &sinfo, NULL) < 0)
        return AFPERR_MISC;

    if (sinfo->sessionkey == NULL || sinfo->sessionkey_len == 0) {
        /* Should never happen. Most likely way too old afpd version */
        LOG_LOGINCONT(log_error, "internal error: afpd's sessionkey not set");
        return AFPERR_MISC;
    }

    /* We skip past the 'username' parameter because all that matters is the ticket */
    p = ibuf;
    while ( *ibuf && ibuflen ) { ibuf++, ibuflen--; }
    if (ibuflen < 4) {
        LOG_LOGINCONT(log_info, "user is %s, no ticket", p);
        return AFPERR_PARAM;
    }

    ibuf++, ibuflen--; /* null termination */

    if ((ibuf - p + 1) % 2) ibuf++, ibuflen--; /* deal with potential padding */

    LOG_LOGINCONT(log_debug, "client thinks user is %s", p);

    /* get the length of the ticket the client sends us */
    memcpy(&ticket_len, ibuf, sizeof(ticket_len));
    ibuf += sizeof(ticket_len); ibuflen -= sizeof(ticket_len);
    ticket_len = ntohs(ticket_len);

    /* a little bounds checking */
    if (ticket_len > ibuflen) {
        LOG_LOGINCONT(log_info,
                      "invalid ticket length (%u > %u)",
                      ticket_len, ibuflen);
        return AFPERR_PARAM;
    }

    /* now try to authenticate */
    if (do_gss_auth(obj, ibuf, ticket_len, rbuf, &rblen, username, userlen, sinfo)) {
        LOG_LOGINCONT(log_info, "do_gss_auth() failed" );
        *rbuflen = 0;
        return AFPERR_MISC;
    }

    /* We use the username we got back from the gssapi client_name.
       Should we compare this to the username the client sent in the clear?
       We know the character encoding of the cleartext username (UTF8), what
       encoding is the gssapi name in? */
    if ((pwd = uam_getname( obj, username, userlen )) == NULL) {
        LOG_LOGINCONT(log_info, "uam_getname() failed for %s", username);
        return AFPERR_NOTAUTH;
    }
    if (uam_checkuser(pwd) < 0) {
        LOG_LOGINCONT(log_info, "`%s'' not a valid user", username);
        return AFPERR_NOTAUTH;
    }

    *rbuflen = rblen;
    *uam_pwd = pwd;
    return AFP_OK;
}