2011-10-11 95 views
6

返回字符串我有一个返回字符串的函数:C:从功能

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

把它放在后面,然后用''''''''''''''''''''或者,腐烂13它两次。 –

+6

如果您打算使用密码,我强烈建议使用散列密码而不是文字字符串。这肯定会减少某人通过在程序上运行“字符串”可以获得的信息量。你可以自定义一个散列函数,这样人们不能(或者至少更难)确定实际的值。 – dbeer

+0

密码的用途是什么?某处登录或登录? –

回答

2

除了安全问题,你要做的是动态分配缓冲区。

您可以采取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; 
} 
+0

我曾经读到过malloc是不好的做法,然后返回它,这就是为什么我总是试图避免这样做。所以谢谢你的第二种方法Alex。你怎么看待传递缓冲区然后重新分配它? –

+0

@Frank。如果在你的客户端代码中你总是想依靠'malloc',那很好。我将编辑答案,向您展示如何做到这一点的示例。 –

+0

非常有帮助。谢谢! –

2

我认为这里的问题是,你试图返回一个指向一个变量的指针,当你试图返回一个像这样的字符串时,这个变量是本地定义的。我期望你的第一个函数能够工作,因为指针将地址返回到一个文字,这个文字在执行程序时是静态的。同样,你可以声明本地作用域中的char []变量是静态的;所以它不在本地范围内。

但老实说,我不明白你为什么要一个函数返回一个指向字符串的指针;当你可以简单地定义在本地范围之外的字面量时,它实际需要的地方。

+0

原因是该函数位于我在运行时动态加载的库中。我这样做是因为我的实时系统使用与测试系统不同的密码。 –

2

我有几个想法:

  1. 存储密码的哈希版本。在getMyPassword()中,解散变量并返回它。

  2. 将密码存储在受保护的文件中(加密,只有您的用户具有读取权限等)。从文件加载密码并返回到您的功能中。

  3. 组合1和2 - 将哈希密码存储在受保护的文件中,并将其解散并返回。

这一切都取决于你想要的安全程度。

+0

我真的很喜欢这个想法,并且已经使用了rot13 hasher。我把它放到加密的库中,并在需要它的二进制文件中进行解密。我将它留在数组样式中以确保没有人可以简单地使用字符串。我现在想尝试一下,如果我可以对库应用不同的权限,而不会破坏我现有的应用程序。 –

1

这或多或少是徒劳的(你知道,任何人在你的程序中都可以很容易地获得密码)。例如,您可以增强一点安全性,请执行以下操作:

  1. 选择要与所有字符异或的“种子”值。
  2. getMyPassword函数来接受该字符。这样,如果你不知道种子,这个函数就没用了。

因此,例如,取值55作为种子。你可以有这样的东西:

char * getMyPassword(char seed) 
{ 
const char* str = "[email protected]"; 
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

非常简单有效。谢谢你的建议迭戈。我可能会将它结合起来,因为我只是添加了一个非常简单的rot13 hasher。 –

+0

这太容易了。如果我查看一个库的公共符号并看到一个函数getMyPassword,我会加倍努力反汇编该函数。如果我后来得到了诸如信用卡信息等客户数据的奖励......必须有另一种方法才能将该密码加入到程序中。程序启动后我会打开/ dev/tty并从键盘上读取它。把它放到lib或配置文件中是不太安全的。 –

0

在考虑到安全问题,将密码安全地传递给进程的常用方式是使用该环境。例如,如果您的程序最终是从网页中调用的,您可以在安全的apache配置文件(通过SetEnv PASSWORD“secret”)中设置一次密码,并将其传递给它运行的每个cgi脚本,以及它们运行的​​任何脚本。然后在你的程序中,你只需要嵌入getenv(“PASSWORD”)。

一个常见的错误是在程序的命令行上接受密码,因为命令行可以被/ proc中的任何进程访问,所以不应该这么做。这就是'ps'如何显示正在运行的内容。此外,您可以将程序权限设置为可执行但不可读(chmod -r + x程序)。所以它可以运行但其内容实际上不能被读取。对于Web服务树中的任何内容,总是一个好主意,以避免由于服务器配置错误而意外泄露事物。这是否适用于shell脚本是依赖于实现的,但它将适用于编译的程序。