0

In my current C project, I am trying implement function to access a json-rpc interface which requires a username/password. With cURL, I managed to sucessfully do that with this command:

curl --user <username>:<password> --data-binary '<json command>' -H 'content-type: text/plain;' <url>

I have this function right now:

const char * send_command(const char * command) {
  int sockfd, n;
  struct sockaddr_in serv_addr;
  struct hostent *server;
  char * buffer = malloc(MAXBUFFER);

  sockfd = socket(AF_INET, SOCK_STREAM, 0);
  if (sockfd < 0)
      error("ERROR opening socket");

  server = gethostbyname(URL);
  if (server == NULL) {
      fprintf(stderr,"ERROR, no such host\n");
      exit(0);
  }

  bzero((char *) &serv_addr, sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
  serv_addr.sin_port = htons(PORT);

  if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
      error("ERROR connecting");

  bzero(buffer,MAXBUFFER);
  const char * result = prepare_statement(command);
  strcpy(buffer, result);
  n = write(sockfd,buffer,strlen(buffer));
  if (n < 0)
       error("ERROR writing to socket");

  bzero(buffer,MAXBUFFER);
  n = read(sockfd,buffer,5*MAXBUFFER);
  if (n < 0)
      error("ERROR reading from socket");

  close(sockfd);
  return buffer;
}

this function kind of work, if no username/password was required. How I could modify this function to allow authenticated access to the json-rpc interface?

Kleber Mota
  • 8,521
  • 31
  • 94
  • 188
  • add `--trace-ascii dump.txt` to your curl command line and then you'll see the full stream curl sent to the server in `dump.txt`. – Daniel Stenberg Dec 12 '17 at 14:08
  • Or use `--libcurl code.c` and instead write a program based on `code.c` to use libcurl to do the same... – Daniel Stenberg Dec 12 '17 at 14:09
  • @DanielStenberg Based on the curl output (`dump.txt`), I added the line `Authorization: Basic ` to the HTTP header. But nothing change: I still getting a empty string as response to my request. About the libcurl option, I am not be able to use it in this project. – Kleber Mota Dec 12 '17 at 17:22
  • This code is absolutely horrible and impossible to make right. Start over. – Daniel Stenberg Dec 12 '17 at 22:26
  • You should get a status line and headers in the response, even if you malform the request. If you're getting status, what is the status code? If not, work on proper HTTP request/response before worrying about authentication. – asynchronos Dec 13 '17 at 18:19
  • Why are you telling `read()` to read 5x the size of your buffer? (`read(sockfd,buffer,5*MAXBUFFER);`) That's a good way to corrupt your heap and crash your program. – asynchronos Dec 13 '17 at 18:23
  • You should `read()` in a loop. You're not guaranteed to get the entire response in one read operation, even if the buffer is sufficient. – asynchronos Dec 13 '17 at 18:25
  • @asynchronos I do not get any response from server (when I try print `buffer`, I got a empty string). Can you indicate to me an example of using `read()` in a loop? I try this: `n=1; while(n>0) n=read(sockfd,buffer,MAXBUFFER);` but this not work either. – Kleber Mota Dec 13 '17 at 23:50
  • @asynchronos also, I have done this kind of request/response in other projects (without authentication) and worked. Is there any extra step to accomplish authentication with the http request besides adding the proper line in the header? – Kleber Mota Dec 14 '17 at 00:04
  • You should check the return value from read (-1 means something different than 0) and the errno in case of error. You might use a packet sniffer like Wireshark to observe and compare what you send with what curl sends. – asynchronos Dec 14 '17 at 20:05

0 Answers0