Just Another Security/Programming Blog: 2015

Friday, 13 March 2015

Specifying an DNS/NS server for address resolution / getaddrinfo in C

I was recently trying to get my C program to use a custom NS server when resolving an address, within the program. It ended up being a challenge to not have to use to create my own function that would have to deal with the connections directly(connect(), etc.)
The purpose of this was to resolve opendns's server to find out the runner's IP address.


I found that 'libresolv' could be used to overwrite a private/protected struct, "_res".
We must include resolv.h to do this.


Here is an example code as to how to do this:

                inet_pton(AF_INET, "208.67.220.220", &server); 

                serverSock.sin_family = AF_INET;
                serverSock.sin_port = htons(53);
                serverSock.sin_addr = server;

                _res.nscount = 1;
                _res.nsaddr_list[0] = serverSock;


Then, using the code to get resolve something:


        if((getaddrinfo("myip.opendns.com", NULL, &hint, (struct addrinfo**)&result)) == 0) {
                p = result;
                h = (struct sockaddr_in *)p->ai_addr;

                printf("myip.opendns.com resolves, using 208.67.220.220, to: %s\n", inet_ntoa(h->sin_addr));
                freeaddrinfo((struct addrinfo *)result);

                exit(0);
        }



Strangely enough, On the first run of getaddrinfo(), resets _res. So, we have to either do a fake getaddrinfo call, or a loop. [It took me 3 hours to work this out :(] -- This is a bug! bug report

Since a loop could cause problems, we're just going to do a fake getaddrinfo call, which is simple enough:

        struct addrinfo hints, *servinfo;



        memset(&hints, 0, sizeof hints);
        getaddrinfo("google.com", NULL, &hints, &servinfo);
        freeaddrinfo((struct addrinfo*)servinfo);


This must be placed before the overwrite of _res, and will use our regular DNS server.

NOTE: _all_ subsequent DNS resolutions within the program will use whatever we packed _res with.
If you want to reset _res afterwards,we would use res_init(); again.


If we did want to use a loop, it would look something like this:


for(int i=0; i<2; i++) {

        if((getaddrinfo("myip.opendns.com", NULL, &hint, (struct addrinfo**)&result)) == 0) {
                p = result;
                h = (struct sockaddr_in *)p->ai_addr;

                printf("myip.opendns.com resolves, using 208.67.220.220, to: %s\n", inet_ntoa(h->sin_addr));
                freeaddrinfo((struct addrinfo *)result);

                exit(0);
        }

}





So, combining all of this, we end up with this code:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <string.h>


int main(void) {

        struct in_addr server;
        struct addrinfo hint, *result=0, *p=0;
        struct sockaddr_in serverSock, *h=0;

        //For our 'fake' resolution
        struct addrinfo hints, *servinfo;


        if(inet_pton(AF_INET, "208.67.220.220", &server) == 0) {
                exit(1);
        }
        //Have to run getaddrinfo before we do this, atleast once, for some reason.
        memset(&hints, 0, sizeof hints);
        getaddrinfo("google.com", NULL, &hints, &servinfo);
        freeaddrinfo((struct addrinfo*)servinfo);

        serverSock.sin_family = AF_INET;
        serverSock.sin_port = htons(53);
        serverSock.sin_addr = server;

        _res.nscount = 1;
        _res.nsaddr_list[0] = serverSock;

        memset(&hint, 0, sizeof hint);

        int error;
        if((error = getaddrinfo("myip.opendns.com", NULL, &hint, (struct addrinfo**)&result)) == 0) {
                p = result;
                h = (struct sockaddr_in *)p->ai_addr;
                char *heh = inet_ntoa(h->sin_addr);
                printf("Our IP is: %s\n", heh);
                freeaddrinfo((struct addrinfo *)result);
                res_init();
                exit(0);
        } else {
                printf("%s\n", gai_strerror(error));
                exit(1);

        }

}

Sunday, 11 January 2015

Incorrect volume in PulseAudio indicator, with fix.

I was encountering a strange bug with PulseAudio, and the indicator/applet that is used to change the volume on my laptop.

I'm using external, Bose Companion 5 speakers, in Ubuntu, with PulseAudio through ALSA.

When I used the speakers, the audio would only come out of them if the pulseaudio("Sound Settings") indicator/applet was set to >90%. That is when audio began to work.

Strangely, it wasn't that it wasn't loud enough, it was because it just wouldn't actually start increasing the real volume.
91% volume in PulseAudio was 11%, 92% was 22%, etc. etc.




This was very irritating because I couldn't, through PulseAudio, choose to have the speakers at the volume, say, 7%.

`alsamixer' correctly set the speaker level, which is how I worked out that PuleAudio would be at around 91% for 10%, etc.

According to the helpful Raymond at bugs.freedesktop.org, "the USB audio only supports 6 channels, and has PCM playback volume control with a very small dB range, from -3.12dB to 0dB."

His recommendation was to add  " ignore_dB=1" to Pulse.

The way I did this, was add to it ~/.pulse/default.pa, since I had already set that file up when I set up my 'secure Ubuntu.'
If I hadn't set it up in ~/.pulse/default.pa, I would have to edit /etc/pulse/default.pa.

I found the line:
"load-module module-udev-detect" in default.pa and replaced it with
"load-module module-udev-detect ignore_dB=1"

And then restarted pulseaudio(`pulseaudio -k')

Likely, there is a way to set this "ignore_dB" option only for the external speakers, compared to the whole of PulseAudio. But the option doesn't seem the affect my internal speakers' usage.