Code_t ZReadAscii16(char *ptr, int len, unsigned short *value_ptr) { unsigned char buf[2]; Code_t retval; retval = ZReadAscii(ptr, len, buf, 2); if (retval != ZERR_NONE) return retval; *value_ptr = (buf[0] << 8) | buf[1]; return ZERR_NONE; }
static Code_t ZCheckAuthentication4(ZNotice_t *notice, struct sockaddr_in *from) { int result; char srcprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4]; KTEXT_ST authent; AUTH_DAT dat; ZChecksum_t checksum; char instance[INST_SZ+1]; if (!notice->z_auth) return ZAUTH_NO; /* Check for bogus authentication data length. */ if (notice->z_authent_len <= 0) return ZAUTH_FAILED; /* Read in the authentication data. */ if (ZReadAscii(notice->z_ascii_authent, strlen(notice->z_ascii_authent)+1, (unsigned char *)authent.dat, notice->z_authent_len) == ZERR_BADFIELD) { return ZAUTH_FAILED; } authent.length = notice->z_authent_len; strcpy(instance, SERVER_INSTANCE); /* We don't have the session key cached; do it the long way. */ result = krb_rd_req(&authent, SERVER_SERVICE, instance, from->sin_addr.s_addr, &dat, srvtab_file); if (result == RD_AP_OK) { ZSetSessionDES(&dat.session); sprintf(srcprincipal, "%s%s%s@%s", dat.pname, dat.pinst[0] ? "." : "", dat.pinst, dat.prealm); if (strcmp(srcprincipal, notice->z_sender)) return ZAUTH_FAILED; } else { return ZAUTH_FAILED; /* didn't decode correctly */ } /* Check the cryptographic checksum. */ checksum = compute_checksum(notice, dat.session); if (checksum != notice->z_checksum) return ZAUTH_FAILED; return ZAUTH_YES; }
Code_t ZReadAscii32(char *ptr, int len, unsigned long *value_ptr) { unsigned char buf[4]; Code_t retval; retval = ZReadAscii(ptr, len, buf, 4); if (retval != ZERR_NONE) return retval; *value_ptr = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; return ZERR_NONE; }
Code_t ZParseNotice(char *buffer, int len, ZNotice_t *notice) { char *ptr, *end; unsigned long temp; int maj, numfields, i; #ifndef __LINE__ #define __LINE__ -1 #endif #define BAD_PACKET(what) return _bad_packet(__LINE__, ptr, notice, what) (void) memset((char *)notice, 0, sizeof(ZNotice_t)); ptr = buffer; end = buffer+len; notice->z_packet = buffer; notice->z_version = ptr; if (strncmp(ptr, ZVERSIONHDR, sizeof(ZVERSIONHDR) - 1)) return (ZERR_VERS); ptr += sizeof(ZVERSIONHDR) - 1; if (!*ptr) BAD_PACKET("null version string"); maj = atoi(ptr); if (maj != ZVERSIONMAJOR) return (ZERR_VERS); ptr = next_field(ptr, end); if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD) BAD_PACKET("parsing num_hdr_fields"); numfields = temp; notice->z_num_hdr_fields = numfields; ptr = next_field(ptr, end); /*XXX 3 */ numfields -= 2; /* numfields, version, and checksum */ if (numfields < 0) BAD_PACKET("no header fields"); if (numfields && ptr < end) { if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD) BAD_PACKET("parsing kind"); notice->z_kind = (ZNotice_Kind_t)temp; numfields--; ptr = next_field(ptr, end); } else BAD_PACKET("missing kind"); if (numfields && ptr < end) { if (ZReadAscii(ptr, end-ptr, (unsigned char *)¬ice->z_uid, sizeof(ZUnique_Id_t)) == ZERR_BADFIELD) BAD_PACKET("parsing uid"); notice->z_time.tv_sec = ntohl((u_long) notice->z_uid.tv.tv_sec); notice->z_time.tv_usec = ntohl((u_long) notice->z_uid.tv.tv_usec); numfields--; ptr = next_field(ptr, end); } else BAD_PACKET("missing uid"); if (numfields && ptr < end) { if (ZReadAscii16(ptr, end-ptr, ¬ice->z_port) == ZERR_BADFIELD) BAD_PACKET("parsing port"); notice->z_port = htons(notice->z_port); numfields--; ptr = next_field(ptr, end); } else BAD_PACKET("missing port"); if (numfields && ptr < end) { if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD) BAD_PACKET("parsing auth"); notice->z_auth = temp; numfields--; ptr = next_field(ptr, end); } else BAD_PACKET("missing auth"); notice->z_checked_auth = ZAUTH_UNSET; if (numfields && ptr < end) { if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD) BAD_PACKET("parsing authenticator length"); notice->z_authent_len = temp; numfields--; ptr = next_field(ptr, end); } else BAD_PACKET("missing authenticator length"); if (numfields && ptr < end) { notice->z_ascii_authent = ptr; numfields--; ptr = next_field(ptr, end); } else BAD_PACKET("missing authenticator field"); if (numfields && ptr < end) { notice->z_class = ptr; numfields--; ptr = next_field(ptr, end); } else notice->z_class = ""; if (numfields && ptr < end) { notice->z_class_inst = ptr; numfields--; ptr = next_field(ptr, end); } else notice->z_class_inst = ""; if (numfields && ptr < end) { notice->z_opcode = ptr; numfields--; ptr = next_field(ptr, end); } else notice->z_opcode = ""; if (numfields && ptr < end) { notice->z_sender = ptr; numfields--; ptr = next_field(ptr, end); } else notice->z_sender = ""; if (numfields && ptr < end) { notice->z_recipient = ptr; numfields--; ptr = next_field(ptr, end); } else notice->z_recipient = ""; if (numfields && ptr < end) { notice->z_default_format = ptr; numfields--; ptr = next_field(ptr, end); } else notice->z_default_format = ""; if (numfields && ptr < end) { notice->z_ascii_checksum = ptr; if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD) notice->z_checksum = 0; else notice->z_checksum = temp; numfields--; ptr = next_field (ptr, end); } else { notice->z_ascii_checksum = ""; notice->z_checksum = 0; } if (numfields && ptr < end) { notice->z_multinotice = ptr; numfields--; ptr = next_field(ptr, end); } else notice->z_multinotice = ""; if (numfields && ptr < end) { if (ZReadAscii(ptr, end-ptr, (unsigned char *)¬ice->z_multiuid, sizeof(ZUnique_Id_t)) == ZERR_BADFIELD) BAD_PACKET("parsing multiuid"); notice->z_time.tv_sec = ntohl((u_long) notice->z_multiuid.tv.tv_sec); notice->z_time.tv_usec = ntohl((u_long) notice->z_multiuid.tv.tv_usec); numfields--; ptr = next_field(ptr, end); } else notice->z_multiuid = notice->z_uid; if (numfields && ptr < end) { /* we will take it on faith that ipv6 addresses are longer than ipv4 addresses */ unsigned char addrbuf[sizeof(notice->z_sender_sockaddr.ip6.sin6_addr)]; int alen; /* because we're paranoid about naughtily misformatted packets */ if (memchr(ptr, '\0', end - ptr) == NULL) BAD_PACKET("unterminated address field"); if (*ptr == 'Z') { if (ZReadZcode((unsigned char *)ptr, addrbuf, sizeof(addrbuf), &alen) == ZERR_BADFIELD) BAD_PACKET("parsing Zcode address"); } else { alen = sizeof(notice->z_sender_sockaddr.ip4.sin_addr); if (ZReadAscii(ptr, end - ptr, (unsigned char *)addrbuf, alen) == ZERR_BADFIELD) BAD_PACKET("parsing NetASCII address"); } if (alen == sizeof(notice->z_sender_sockaddr.ip6.sin6_addr)) { notice->z_sender_sockaddr.ip6.sin6_family = AF_INET6; memcpy(¬ice->z_sender_sockaddr.ip6.sin6_addr, addrbuf, alen); #ifdef HAVE_SOCKADDR_IN6_SIN6_LEN notice->z_sender_sockaddr.ip6.sin6_len = sizeof(notice->z_sender_sockaddr.ip6); #endif } else if (alen == sizeof(notice->z_sender_sockaddr.ip4.sin_addr)) { notice->z_sender_sockaddr.ip4.sin_family = AF_INET; memcpy(¬ice->z_sender_sockaddr.ip4.sin_addr, addrbuf, alen); #ifdef HAVE_SOCKADDR_IN_SIN_LEN notice->z_sender_sockaddr.ip4.sin_len = sizeof(notice->z_sender_sockaddr.ip4); #endif } else BAD_PACKET("address claims to be neither IPv4 or IPv6"); numfields--; ptr = next_field(ptr, end); } else { memset(¬ice->z_sender_sockaddr, 0, sizeof notice->z_sender_sockaddr); notice->z_sender_sockaddr.ip4.sin_family = AF_INET; notice->z_sender_sockaddr.ip4.sin_addr = notice->z_uid.zuid_addr; #ifdef HAVE_SOCKADDR_IN_SIN_LEN notice->z_sender_sockaddr.ip4.sin_len = sizeof(notice->z_sender_sockaddr.ip4); #endif } if (numfields && ptr < end) { if (ZReadAscii16(ptr, end-ptr, ¬ice->z_charset) == ZERR_BADFIELD) BAD_PACKET("parsing charset"); notice->z_charset = htons(notice->z_charset); numfields--; ptr = next_field(ptr, end); } else notice->z_charset = ZCHARSET_UNKNOWN; for (i=0;ptr < end && i<Z_MAXOTHERFIELDS && numfields;i++,numfields--) { notice->z_other_fields[i] = ptr; ptr = next_field(ptr, end); } notice->z_num_other_fields = i; for (i=0;ptr < end && numfields;numfields--) ptr = next_field(ptr, end); if (numfields || *(ptr - 1) != '\0') BAD_PACKET("end of headers"); notice->z_message = (void *)ptr; notice->z_message_len = len-(ptr-buffer); return (ZERR_NONE); }