Unix Programming Frequently Asked Questions - Part IV

Unix Programming Frequently Asked Questions - Part IV


4. System Information

4.1 How can I tell how much memory my system has?

This is another `Frequently Unanswered Question'. In most cases, youshould not even attempt to find out.

If you really must, then it can usually be done, but in a highlysystem-dependent fashion. For example, on Solaris, you can usesysconf(_SC_PHYS_PAGES) and sysconf(_SC_PAGESIZE); onFreeBSD, you can use sysctl(); on Linux you can read and parse`/proc/meminfo' (being careful to allow any of the historicallyvalid formats for this file); other systems may have their own methods.I'm not aware of any more portable methods.

For HP-UX (9 and 10), the following code has been contributed:

struct pst_static pst;

if (pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0) != -1)
{
    printf(" Page Size: %lu\n", pst.page_size);
    printf("Phys Pages: %lu\n", pst.physical_memory);
}

4.2 How do I check a user's password?

4.2.1 How do I get a user's password?

Traditionally user passwords were kept in the `/etc/passwd' file,on most UNIX flavours. Which is usually of this format:

username:password:uid:gid:gecos field:home directory:login shell

Though this has changed with time, now user information may be kept onother hosts, or not necessarily in the `/etc/passwd' file. Modernimplementations also made use of `shadow' password files which hold thepassword, along with sensitive information. This file would be readableonly by privileged users.

The password is usually not in clear text, but encrypted due to securityconcerns.

POSIX defines a suite of routines which can be used to access thisdatabase for queries. The quickest way to get an individual record for auser is with the getpwnam() and getpwuid() routines. Bothreturn a pointer to a struct passwd, which holds the users informationin various members. getpwnam() accepts a string holding theuser's name, getpwuid() accepts a uid (type uid_t asdefined by POSIX). Both return NULL if they fail.

However, as explained earlier, a shadow database exists on most modernsystems to hold sensitive information, namely the password. Some systemsonly return the password if the calling uid is of the superuser, othersrequire you to use another suite of functions for the shadow passworddatabase. If this is the case you need to make use of getspnam(),which accepts a username and returns a struct spwd. Again, in order tosuccessfully do this, you will need to have privileges. (On some systems,notably HP-UX and SCO, you may need to use getprpwnam() instead.)

4.2.2 How do I get shadow passwords by uid?

My system uses the getsp* suite of routines to get the sensitive userinformation. However I do not have getspuid(), onlygetspnam(). How do I work around this, and get by uid?

The work around is relatively painless. The following routine should gostraight into your personal utility library:

#include <stdlib.h>
#include <stdio.h>

#include <pwd.h>
#include <shadow.h>

struct spwd *getspuid(uid_t pw_uid)
{
  struct spwd *shadow;
  struct passwd *ppasswd;

  if( ((ppasswd = getpwuid(pw_uid)) == NULL) 
      || ((shadow = getspnam(ppasswd->pw_name)) == NULL))
    return NULL;
  
  return shadow;
}

The problem is, that some systems do not keep the uid, or otherinformation in the shadow database.

4.2.3 How do I verify a user's password?

The fundamental problem here is, that various authentication systemsexist, and passwords aren't always what they seem. Also with thetraditional one way encryption method used by most UNIX flavours (out ofthe box), the encryption algorithm may differ, some systems use a oneway DES encryption, others like the international release of FreeBSD useMD5.

The most popular way is to have a one way encryption algorithm, wherethe password cannot be decrypted. Instead the password is taken in cleartext from input, and encrypted and checked against the encryptedpassword in the database. The details of how to encrypt should reallycome from your man page for crypt(), but here's a usual version:

/* given a plaintext password and an encrypted password, check if
 * they match; returns 1 if they match, 0 otherwise.
 */

int check_pass(const char *plainpw, const char *cryptpw)
{
    return strcmp(crypt(plainpw,cryptpw), cryptpw) == 0;
}

This works because the salt used in encrypting the password is stored asan initial substring of the encrypted value.

WARNING: on some systems, password encryption is actually donewith a variant of crypt called bigcrypt().

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值