我有一个返回字符串的函数:
const *char getMyPassword()
{
return "mysecretpassword";
}
嗯,它工作得很好,但我发现如果我在Unix系统上运行“字符串”,它会显示在列表中......不是很好。
更换它的最简单方法是什么?该函数位于库中,我希望保持灵活性。我现在开始在函数内进行mallocing,字符串中的字符串消失了。但是,我何时可以再次释放它?
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并传递指针,那么我怎么能知道之前的大小,因为密码大小只在函数中知道?
作为一个计划B我可以通过一个巨大的阵列,但这似乎不是很优雅。我该怎么做呢?
编辑:我添加了strcpy(return_arr,arr)。我实际上是在原始代码中使用它,但在这里忘记了它。
答案 0 :(得分:2)
我认为这里的问题是,当你试图返回一个像这样的字符串时,你试图返回一个指向本地定义的变量的指针。我希望你的第一个函数能够工作,因为指针将地址返回给文字,这通过执行程序是静态的。同样,您可以将本地范围中的char []变量声明为静态;所以它不在本地范围内。
但老实说,我不明白为什么你想要一个函数返回一个指向字符串文字的指针;当你可以简单地定义局部范围之外的文字时,实际需要它。
答案 1 :(得分:2)
我有一些想法:
存储密码的哈希版本。在getMyPassword()中,取消变量并将其返回。
将密码存储在受保护的文件中(加密,仅对您的用户具有读取权限等)。从文件中加载密码并在函数中返回。
合并1和2 - 将散列密码存储在受保护的文件中,取消隐藏并返回。
这完全取决于你想要的安全程度。
答案 2 :(得分:2)
除了安全问题之外,您要做的是动态分配缓冲区。
你可以采取两种方法。
malloc
并记录它返回malloced
结果。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;
}
答案 3 :(得分:1)
这或多或少是徒劳的(你知道,任何逆转你的程序的人都可以轻松获得密码)隐写术练习。例如,您可以增强安全性,请执行以下操作:
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是什么:)
答案 4 :(得分:0)
关于安全问题,将密码安全地传递给进程的常用方法是使用环境。例如,如果您的程序最终从网页调用,您可以在安全apache配置文件中设置一次密码(通过SetEnv PASSWORD“secret”),它将传递给它运行的每个cgi脚本,以及它们运行的任何内容。然后在你的程序中你只需要嵌入getenv(“密码”)。
一个常见的错误是在程序的命令行上接受密码,这不应该这样做,因为命令行可以被/ proc中的任何进程访问。这就是'ps'如何显示正在运行的内容。
此外,您可以将程序权限设置为可执行但不可读(chmod -r + x程序)。所以它可以运行但其内容实际上无法读取。对于Web服务树中的任何内容总是一个好主意,以避免因服务器配置错误而意外泄露事物。这是否适用于shell脚本是依赖于实现的,但它适用于已编译的程序。