C: возвращение строки из функции - PullRequest
6 голосов
/ 12 октября 2011

У меня есть функция, которая возвращает строку:

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

Ну, это сработало отлично, но я обнаружил, что если я буду запускать "строки" в системах Unix, это появится в списке ... не хорошо

Какой самый простой способ заменить его? Функция находится в библиотеке, и я хочу сохранить ее гибкость. Теперь я начал неправильное использование функции, и строка в строках исчезла. Тем не менее, когда я смогу освободить его снова?

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;

}

Если бы я должен был выполнить malloc раньше и передать указатель, то как я мог узнать размер раньше, поскольку размер паролей известен только внутри функции?

В качестве плана Б я мог бы передать огромный массив, но это выглядит не очень элегантно. Как мне подойти к этому?

РЕДАКТИРОВАТЬ: я добавил strcpy (return_arr, arr). Я действительно имел это в оригинальном коде, но забыл это здесь.

Ответы [ 5 ]

2 голосов
/ 12 октября 2011

Помимо проблем безопасности, вы пытаетесь динамически распределить буфер.

Вы можете использовать 2 подхода.

  1. Всегда malloc внутри вашей функции и документируйте, что она возвращает malloced результат.
  2. Следуйте пути некоторых стандартных библиотечных функций, требуйте, чтобы пользователь передал указатель на допустимый буфер и его размер и возвратил фактически скопированный размер. Некоторые из этих функций разрешают проход check, когда вы передаете буфер null, они не пытаются выделить его, а вместо этого возвращают размер, необходимый для хранения структуры.

Мне кажется, что вы уже реализовали подход № 1.

Для подхода № 2 используйте эту подпись:

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;
}

Преимущество метода # 2 заключается в том, что вызывающая сторона во многих случаях может выделять буфер в стеке, особенно если вы объявляете максимальный требуемый размер буфера. Еще одним преимуществом является то, что управление памятью теперь полностью обрабатывается клиентом. В библиотеке общего назначения вы не хотите создавать клиента в зависимости от конкретной схемы распределения памяти библиотеки.

В ответ на комментарий

Если вы всегда хотите использовать выделенное значение в своем клиентском коде, то я бы так и сделал:

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;
}
2 голосов
/ 12 октября 2011

У меня есть несколько идей:

  1. Сохраните хешированную версию пароля.В getMyPassword () снимите хэш с переменной и верните ее.

  2. Сохраните пароль в защищенном файле (зашифрованном, с правами на чтение только для вашего пользователя и т. Д.).Загрузите пароль из файла и вернитесь в свою функцию.

  3. Объедините 1 и 2 - сохраните хешированный пароль в защищенном файле, распакуйте его и верните.

Все зависит от того, насколько безопасным вы хотите быть.

2 голосов
/ 12 октября 2011

Я думаю, что проблема здесь в том, что вы пытаетесь вернуть указатель на переменную, которая определяется локально, когда вы пытаетесь вернуть такую ​​строку.Я ожидаю, что ваша первая функция будет работать, так как указатель возвращает адрес в литерал, который является статическим при выполнении программы.Точно так же вы можете объявить переменную char [] в вашей локальной области видимости как статическую;так что это не входит в локальную область.

Но, честно говоря, я не понимаю, почему вы хотите, чтобы функция возвращала указатель на строковый литерал;когда вы можете просто определить литерал вне локальной области видимости, где он на самом деле нужен.

1 голос
/ 12 октября 2011

Это более или менее бесполезное (вы знаете, любой, кто обратится к вашей программе может легко получить пароль) упражнение на стеганографию.Например, вы можете немного повысить безопасность, сделав следующее:

  1. Выберите «начальное» значение для XOR со всеми символами.
  2. Выполните функцию getMyPassword, чтобы принять этот символ.Таким образом, функция в большинстве случаев бесполезна, если вы не знаете начальное число.

Так, например, возьмите значение 55 в качестве начального числа.У вас может быть что-то вроде:

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;
}

, и вам нужно позвонить getMyPassword(55), чтобы получить правильный результат.Клянусь, номер 55 был выбран случайным образом, и я не знаю, что такое DDVG:)

0 голосов
/ 13 февраля 2014

Что касается вопросов безопасности, распространенным способом безопасной передачи паролей процессу является использование среды. Например, если ваша программа в конечном счете вызывается с веб-страницы, вы можете один раз установить пароль в защищенных конфигурационных файлах apache (через SetEnv PASSWORD «secret»), и он будет передан каждому выполняемому скрипту cgi и тому, что они запускают , Тогда в вашу программу нужно только встроить getenv («ПАРОЛЬ»).

Распространенной ошибкой является принятие паролей в командной строке программы, этого не следует делать, поскольку к командной строке может обращаться любой процесс в / proc. Вот как «ps» может показать, например, что работает.

Кроме того, вы можете установить права доступа ваших программ к исполняемым, но не читаемым (chmod -r + x program). Таким образом, он может быть запущен, но его содержимое на самом деле не может быть прочитано. Всегда хорошая идея для чего-либо в вашем дереве веб-обслуживания, чтобы избежать случайного раскрытия информации из-за ошибки конфигурации сервера. Работает ли это для сценариев оболочки, зависит от реализации, но будет работать для скомпилированных программ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...