static void chap_process_challenge(struct ppp_chap *chap, const guint8 *packet) { const struct chap_header *header = (const struct chap_header *) packet; struct chap_header *response; GChecksum *checksum; const char *secret = g_at_ppp_get_password(chap->ppp); const char *username = g_at_ppp_get_username(chap->ppp); guint16 response_length; struct ppp_header *ppp_packet; gsize digest_len; /* create a checksum over id, secret, and challenge */ checksum = g_checksum_new(chap->method); if (checksum == NULL) return; g_checksum_update(checksum, &header->identifier, 1); if (secret) g_checksum_update(checksum, (guchar *) secret, strlen(secret)); g_checksum_update(checksum, &header->data[1], header->data[0]); /* transmit a response packet */ /* * allocate space for the header, the checksum, and the ppp header, * and the value size byte */ digest_len = g_checksum_type_get_length(chap->method); response_length = digest_len + sizeof(*header) + 1; if (username != NULL) response_length += strlen(username); ppp_packet = ppp_packet_new(response_length, CHAP_PROTOCOL); if (ppp_packet == NULL) goto challenge_out; response = (struct chap_header *) &ppp_packet->info; if (response) { response->code = RESPONSE; response->identifier = header->identifier; response->length = htons(response_length); g_checksum_get_digest(checksum, response->data + 1, &digest_len); response->data[0] = digest_len; /* leave the name empty? */ } if (username != NULL) memcpy(response->data + digest_len + 1, username, strlen(username)); /* transmit the packet */ ppp_transmit(chap->ppp, (guint8 *) ppp_packet, response_length); g_free(ppp_packet); challenge_out: g_checksum_free(checksum); }
static struct pppcp_packet *pppcp_packet_new(struct pppcp_data *data, guint type, guint bufferlen) { struct pppcp_packet *packet; struct ppp_header *ppp_packet; guint16 packet_length = bufferlen + sizeof(*packet); ppp_packet = ppp_packet_new(packet_length, data->driver->proto); if (ppp_packet == NULL) return NULL; /* advance past protocol to add CP header information */ packet = (struct pppcp_packet *) (ppp_packet->info); packet->length = htons(packet_length); packet->code = type; return packet; }
struct ppp_net *ppp_net_new(GAtPPP *ppp, int fd) { struct ppp_net *net; GIOChannel *channel = NULL; struct ifreq ifr; int err; net = g_try_new0(struct ppp_net, 1); if (net == NULL) goto badalloc; net->ppp_packet = ppp_packet_new(MAX_PACKET, PPP_IP_PROTO); if (net->ppp_packet == NULL) goto error; /* * If the fd value is still the default one, * open the tun interface and configure it. */ memset(&ifr, 0, sizeof(ifr)); if (fd < 0) { /* open a tun interface */ fd = open("/dev/net/tun", O_RDWR); if (fd < 0) goto error; ifr.ifr_flags = IFF_TUN | IFF_NO_PI; strcpy(ifr.ifr_name, "ppp%d"); err = ioctl(fd, TUNSETIFF, (void *) &ifr); if (err < 0) goto error; } else { err = ioctl(fd, TUNGETIFF, (void *) &ifr); if (err < 0) goto error; } net->if_name = strdup(ifr.ifr_name); /* create a channel for reading and writing to this interface */ channel = g_io_channel_unix_new(fd); if (channel == NULL) goto error; if (!g_at_util_setup_io(channel, 0)) goto error; g_io_channel_set_buffered(channel, FALSE); net->channel = channel; net->watch = g_io_add_watch(channel, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, ppp_net_callback, net); net->ppp = ppp; net->mtu = MAX_PACKET; return net; error: if (channel) g_io_channel_unref(channel); g_free(net->if_name); g_free(net->ppp_packet); g_free(net); badalloc: if (fd >= 0) close(fd); return NULL; }