C++


Fedora 24: Solution to gcrypt.h: No such file or directory

Recently we tried to compile cisco-decrypt.c* on Fedora 24 (64bit).
We got the full source code from the website of Maurice Massar.
Download full source code here: [download id=”2078″]

We needed this tool to configure the Gnome 3 native network client to connect to a specific Cisco VPN network.
During the configuration we setup a “Cisco Compatible VPN (vpnc)” VPN.

* Please note that this tool is NOT a hacking nor cracking tool. In order for you to make any use of it, you need to have a valid PCF file given to you by your system administrator. It is only useful when you need to get the group password to configure a system that does not accept the PCF file with the encrypted password.

To compile the code you can use one of the following two methods:

Compilation method 1

gcc -Wall -o cisco-decrypt cisco-decrypt.c $(libgcrypt-config --libs --cflags)

If the package libgcrypt-devel is not installed you will get a prompt message as follows, which will instruct you to install the missing package.
You need to type y to both questions so that the installation will proceed. Once the installation is done, execute once more the compilation command.

As you can see below, you might get a whole bunch of errors, ignore them and try to compile once more. It seems to be a bug that will not affect the end result (at least in this scenario).

gcc -Wall -o cisco-decrypt cisco-decrypt.c $(libgcrypt-config --libs --cflags)
bash: libgcrypt-config: command not found...
Install package 'libgcrypt-devel' to provide command 'libgcrypt-config'? [N/y] y

Proceed with changes? [N/y] y

gcc: error: Waiting: No such file or directory
gcc: error: in: No such file or directory
gcc: error: queue...: No such file or directory
gcc: error: Loading: No such file or directory
gcc: error: list: No such file or directory
gcc: error: of: No such file or directory
gcc: error: packages....: No such file or directory
gcc: error: The: No such file or directory
gcc: error: following: No such file or directory
gcc: error: packages: No such file or directory
gcc: error: have: No such file or directory
gcc: error: to: No such file or directory
gcc: error: be: No such file or directory
gcc: error: installed:: No such file or directory
gcc: error: libgcrypt-devel-1.6.6-1.fc24.x86_64: No such file or directory
gcc: error: Development: No such file or directory
gcc: error: files: No such file or directory
gcc: error: for: No such file or directory
gcc: error: the: No such file or directory
gcc: error: libgcrypt: No such file or directory
gcc: error: package: No such file or directory
gcc: error: libgpg-error-devel-1.24-1.fc24.x86_64: No such file or directory
gcc: error: Development: No such file or directory
gcc: error: files: No such file or directory
gcc: error: for: No such file or directory
gcc: error: the: No such file or directory
gcc: error: libgpg-error: No such file or directory
gcc: error: package: No such file or directory
gcc: error: Waiting: No such file or directory
gcc: error: in: No such file or directory
gcc: error: queue...: No such file or directory
gcc: error: Waiting: No such file or directory
gcc: error: for: No such file or directory
gcc: error: authentication...: No such file or directory
gcc: error: Waiting: No such file or directory
gcc: error: in: No such file or directory
gcc: error: queue...: No such file or directory
gcc: error: Downloading: No such file or directory
gcc: error: packages...: No such file or directory
gcc: error: Requesting: No such file or directory
gcc: error: data...: No such file or directory
gcc: error: Testing: No such file or directory
gcc: error: changes...: No such file or directory
gcc: error: Installing: No such file or directory
gcc: error: packages...: No such file or directory

Compilation method 2

In case the above method does not work for you for some reason, you can try the following.

gcc -Wall -o cisco-decrypt cisco-decrypt.c -lgcrypt

If the package libgcrypt-devel is not installed you will get an error as follows.

gcc -Wall -o cisco-decrypt cisco-decrypt.c -lgcrypt
cisco-decrypt.c:30:20: fatal error: gcrypt.h: No such file or directory
 #include <gcrypt.h>
                    ^
compilation terminated.

In this case use

sudo dnf install libgcrypt-devel

to install the missing library and try again to compile.

To use

Open your PCF file with a text editor. Find the line that starts with enc_GroupPwd= and copy the characters after that.

Paste the characters as the first command line argument to the newly compiled application. The password will be the line returned right after.


./cisco-decrypt 886E2FC74BFCD8B6FAF47784C386A50D0C1A5D0528D1E682B7EBAB6B2E91E792E389914767193F9114FA26C1E192034754F85FC97ED36509
Th!sIsMyK3y#

Other notes

In the case you get these errors:

/tmp/ccHrH1kZ.o: In function `c_decrypt':
cisco-decrypt.c:(.text+0x243): undefined reference to `gcry_md_hash_buffer'
cisco-decrypt.c:(.text+0x267): undefined reference to `gcry_md_hash_buffer'
cisco-decrypt.c:(.text+0x2b4): undefined reference to `gcry_md_hash_buffer'
cisco-decrypt.c:(.text+0x31d): undefined reference to `gcry_cipher_open'
cisco-decrypt.c:(.text+0x33b): undefined reference to `gcry_cipher_setkey'
cisco-decrypt.c:(.text+0x356): undefined reference to `gcry_cipher_setiv'
cisco-decrypt.c:(.text+0x382): undefined reference to `gcry_cipher_decrypt'
cisco-decrypt.c:(.text+0x391): undefined reference to `gcry_cipher_close'
/tmp/ccHrH1kZ.o: In function `main':
cisco-decrypt.c:(.text+0x41e): undefined reference to `gcry_check_version'
collect2: error: ld returned 1 exit status

It most probably means that you did not add on your compilation command one of the following two parameters

  1. $(libgcrypt-config –libs –cflags)
  2. -lgcrypt

You need one of these two options to be on the command line to compile.


C/C++: How NOT to define multiple pointers

When defining pointers in C/C++ you should be careful on how you use the * characters. If you try to define multiple pointers on the same line and you do not add the * character in front of each variable, then the results will not be what you would expect. In the following examples we added the * to the data type definition, hoping that all variables would become pointers of that data type. Unfortunately, as the compiler points out later on while making the comparisons, only the first variable in each line becomes a pointer of the data type.

Wrong Examples

C Source Code:

#include <stdio.h>

int main()
{
    int* a, b;
    int *c, d;
    int * e, f;

    a == b;
    c == d;
    e == f;

    return 0;
}

Compiler Output:

$ gcc -o main *.c                                                                                          
main.c: In function 'main':                                                                                      
main.c:9:7: warning: comparison between pointer and integer                                                      
     a == b;                                                                                                     
       ^                                                                                                         
main.c:10:7: warning: comparison between pointer and integer                                                     
     c == d;                                                                                                     
       ^                                                                                                         
main.c:11:7: warning: comparison between pointer and integer                                                     
     e == f;                                                                                                     
       ^                                                                                                         

C++ Source Code:

#include <iostream>
using namespace std;

int main()
{
    int* a, b;
    int *c, d;
    int * e, f;

    a == b;
    c == d;
    e == f;

   return 0;
}

Compiler Output:

$ g++ -std=c++11 *.cpp -o main

main.cpp: In function ‘int main()’:
main.cpp:10:10: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
     a == b;
          ^
main.cpp:11:10: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
     c == d;
          ^
main.cpp:12:10: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
     e == f;
          ^

Correct Examples

#include <stdio.h>

int main()
{
    int* a, * b;
    int *c, *d;
    int * e, * f;

    a == b;
    c == d;
    e == f;

    return 0;
}
#include <iostream>
using namespace std;

int main()
{
    int* a, * b;
    int *c, *d;
    int * e, * f;

    a == b;
    c == d;
    e == f;

   return 0;
}

C++: Get size of enum 1

We used the following application in C++ to test the size of an enum:

#include <iostream>
using namespace std;

enum SINGLE {
        S_ZERO = 0x0,
        S_FULL = 0xFFFFFFFF
};

enum DOUBLE {
        D_ZERO = 0x0,
        D_FULL = 0xFFFFFFFFFFFFFFFF
};

int main() {
        cout << "Single Zero: Size '" << sizeof(S_ZERO) << "' Value '" << S_ZERO << "'" << endl;
        cout << "Double Zero: Size '" << sizeof(D_ZERO) << "' Value '" << D_ZERO << "'" << endl;

        cout << "Single Full: Size '" << sizeof(S_FULL) << "' Value '" << S_FULL << "'" << endl;
        cout << "Double Full: Size '" << sizeof(D_FULL) << "' Value '" << D_FULL << "'" << endl;
        return 0;
}

The output we got is the following:

Single Zero: Size '4' Value '0'
Double Zero: Size '8' Value '0'
Single Full: Size '4' Value '4294967295'
Double Full: Size '8' Value '18446744073709551615'

From the result it is pretty easy to understand that the size of an enum will grow to 64bit when any of its values is greater than 32bit.

For our test we used g++ (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6) on a 64bit Fedora 23.


C/C++: Pass random value from parent to child after fork() via a pipe()

The following code will create a pipe for each child, fork the process as many times as it is needed and send from the parent to each child a random int value, finally the children will read the value and terminate.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
int main(int argc, char *argv[]) {
    int count = 3;
    int fd[count][2];
    int pid[count];
    srand(time(NULL));

    // create pipe descriptors
    for (int i = 0; i < count; i++) {
        pipe(fd[i]);
        // fork() returns 0 for child process, child-pid for parent process.
        pid[i] = fork();
        if (pid[i] != 0) {
            // parent: writing only, so close read-descriptor.
            close(fd[i][0]);

            // send the value on the write-descriptor.
            int r = rand();
            write(fd[i][1], &r, sizeof(r));
            printf("Parent(%d) send value: %d\n", getpid(), r);

            // close the write descriptor
            close(fd[i][1]);
        } else {
            // child: reading only, so close the write-descriptor
            close(fd[i][1]);

            // now read the data (will block)
            int id;
            read(fd[i][0], &id, sizeof(id));
            printf("%d Child(%d) received value: %d\n", i, getpid(), id);

            // close the read-descriptor
            close(fd[i][0]);
            //TODO cleanup fd that are not needed
            break;
        }
    }
    return 0;
}