开发者

C: Returning string from function

开发者 https://www.devze.com 2023-04-12 03:43 出处:网络
I have a function that returns a string: const *char getMyPassword() { return \"mysecretpassword\"; } Well, it worked perfectly, but I discovered that if I would run \"strings\" on Unix systems it

I have a function that returns a string:

const *char getMyPassword()
{
    return "mysecretpassword";
}

Well, it worked perfectly, but I discovered that if I would run "strings" on Unix systems it shows up in the list.. not good.

What is the easiest possible way to replace it? The function sits in a library and I want to keep it flexible. I now started mallocing within the function and the str开发者_运维技巧ing in strings disappeared. However, when would I free it again?

char * getMyPassword()
{
unsigned char arr[] = { 'p', 'a', 's', 's', 'w', 'o', 'r' , 'd', '\0' };
char *return_arr = malloc(sizeof(arr));
strcpy(return_arr, arr);
return return_arr;

}

If I was to malloc before and pass a pointer, then how could I have known the size before as the passwords size is only known within the function?

As a plan B I could pass a huge array, but that seems not very elegant. How should I approach this?

EDIT: I added the strcpy(return_arr, arr). I actually had it in the original code, but forgot it in here.


Security issues aside, what you are trying to do is dynamically allocate buffer.

You can take 2 approaches.

  1. Always malloc inside your function and document it that it returns malloced result.
  2. Follow the road of some standard library functions, require that user pass a pointer to a valid buffer and its size and return the size actually copied. Some of these functions allow the check pass, when you pass in a null buffer, they do not try to allocate it, but instead return the size that is required to hold the structure.

Looks to me that you've already implemented approach #1.

For approach #2 use this signature:

int getMyPassword( char* buffer, size_t buff_size, size_t* p_num_copied )
{
  unsigned char arr[] = { 'p', 'a', 's', 's', 'w', 'o', 'r' , 'd', '\0' };

  if ( buffer == 0 )
  {
    *p_num_copied = sizeof(arr);
    return SUCCESS;
  }

  if ( buff_size < sizeof(arr) )
  {
    *p_num_copied = sizeof(arr);
    return BUFFER_TOO_SMALL;
  }

  memcpy( buffer, arr, sizeof(arr) );

  *p_num_copied = sizeof( arr );

  return SUCCESS;
}

Advantage of method #2 is that the caller, in many cases, may allocate the buffer on stack, especially if you advertise the maximum required buffer size. Another advantage is that memory management is now completely handled by client. In general purpose library you don't want to make a client depending on a particular library memory allocation schema.

IN REPLY TO COMMENT

If you always want to use allocated value in your client code, then this is how I would do this:

char* clientGetPasswordFromLibrary( )
{
  // in our day and age it's fine to allocate this much on stack
  char buffer[256];
  size_t num_copied;

  int status = getMyPassword( buffer, sizeof(buffer), &num_copied );

  char* ret_val = NULL;

  if ( status == BUFFER_TOO_SMALL )
  {
    ret_val = malloc( num_copied );

    if ( ret_val == NULL )
    {
      return NULL;
    }

    getMyPassword( ret_val, num_copied, &num_copied );
  }
  else
  {
    ret_val = malloc( num_copied );

    if ( ret_val == NULL )
    {
      return NULL;
    }

    memcpy( ret_val, buffer, num_copied );
  }

  return ret_val;
}


I think the problem here is, you're trying to return a pointer to a variable which is locally defined when you're trying to return a string like that. I'd expect your first function to work, since the pointer returns the address to a literal, which is static through the execution of the program. Similarly, you could declare the the char [] variable in your local scope to be static; so that it's not in the local scope.

But honestly, I do not understand why you'd want a function to return a pointer to a string literal; when you can simply define the literal outside the local scope, where it is actually needed.


I have a few ideas:

  1. Store the hashed version of the password. In getMyPassword(), unhash the variable and return it.

  2. Store the password in a protected file (encrypted, with read permissions for only your user, etc). Load the password from the file and return in in your function.

  3. Combine 1 and 2 - store the hashed password in the protected file, unhash it and return it.

It all depends on how secure you want to be.


It is a more or less futile (you know, anyone reverse-ingeneering your program can get the password easily) steganography exercise. You can, for example, to enhance a little bit more the security, do the following:

  1. Select a "seed" value to be XOR'ed with all the characters.
  2. Do the getMyPassword function to accept that character. This way, the function is mostly useless if you don't know the seed.

So, for example, take the value 55 as your seed. You can have something like:

char * getMyPassword(char seed)
{
const char* str = "SEX@DDVG";
char *return_arr = malloc(9); /* 8+1 */
for (int i=0 ; i < 9 ; ++i)
   return_arr[i] = str[i] ^ seed;
return_arr[i] = 0;
return return_arr;
}

and you have to call getMyPassword(55) to get the correct result. I swear, the number 55 was chosen at random, and I don't know what DDVG is :)


In regard to the security issues, A common way to pass passwords securely to a process is using the environment. For instance, if your program is eventually called from a web page you can set the password once in the secure apache config files (via SetEnv PASSWORD "secret") and it will be passed down to every cgi script it runs, and whatever they run. Then in your program you only need to embed getenv("PASSWORD").

A common mistake is to accept passwords on the command line of a program, this should not be done because the command line can be accessed by any process in /proc. This is how 'ps' can show what is running for instance.

Also, you can set your programs permission to executable but not readable (chmod -r+x program). So it can be run but its contents can not actually be read. Always a good idea for anything in your web serving tree to avoid exposing things by accident via a server configuration error. Whether this works for shell scripts is implementation dependent but it will work for compiled programs.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号