/* 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; }
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; }