não pode useradd / adduser quando / etc / {passwd, shadow, group} são symlink (debian squeeze)

4

Estou com problemas com o useradd quando estou em movimento     / etc / passwd     / etc / shadow     / etc / group de / etc para / home e crie um symlink para ter o / etc / {passwd, shadow, group} apontando para / home / {passwd, shadow, group}

não consigo criar nenhum usuário e ter saída de useradd:

root@client:/home# useradd testuser
Adding user 'testuser' ...
Adding new group 'testuser' (1000) ...
groupadd: cannot open /etc/group

btw saída do useradd é

root@client:/home# adduser testuser
useradd: cannot open /etc/passwd
    
por Mickael Ciocca 25.03.2013 / 10:00

2 respostas

22

Por que useradd se recusa a abrir um link simbólico /etc/passwd ?

Para responder a pergunta, precisamos dar uma olhada no código-fonte de useradd (eu fiz isso no Ubuntu 12.04, no Debian ele pode ser um pouco diferente):

  1. Descubra qual pacote possui /usr/sbin/useradd :

    $ dpkg-query -S /usr/sbin/useradd
    passwd: /usr/sbin/useradd
    
  2. Instale a fonte:

    $ apt-get source passwd
    Reading package lists... Done
    Building dependency tree       
    Reading state information... Done
    Picking 'shadow' as source package instead of 'passwd'
    (...)
    dpkg-source: info: extracting shadow in shadow-4.1.4.2+svn3283
    dpkg-source: info: unpacking shadow_4.1.4.2+svn3283.orig.tar.gz
    dpkg-source: info: applying shadow_4.1.4.2+svn3283-3ubuntu5.1.diff.gz
    (...)
    
  3. cd no diretório de origem:

    $ cd shadow-4.1.4.2+svn3283/
    
  4. Pesquise no diretório o arquivo de origem de useradd , que idealmente deve ser chamado de useradd.c :

    $ find . -name useradd.c
    ./src/useradd.c
    

    Bingo!

  5. Procure a mensagem de erro cannot open /etc/passwd (na verdade, só pesquiso cannot open , pois a string inteira não retorna nenhum resultado):

    $ grep -B 1 'cannot open' src/useradd.c
    (...)
      if (pw_open (O_RDWR) == 0) {
          fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ());
    (...)
    

    -B 1 significa imprimir 1 linha do contexto principal antes da linha correspondente.

    Aqui é onde a mensagem de erro que você vê está sendo gerada. A função pw_open controla se /etc/passwd pode ser aberto ou se deve ser gerado um erro.

    pw_open não é um syscall do Linux ( apropos pw_open não retorna nenhum resultado), então é provavelmente implementado dentro deste pacote. Vamos procurar por isso.

  6. Rastrear pw_open leva a:

    $ grep -R pw_open * 
    (...)
    lib/pwio.c:int pw_open (int mode)
    (...)
    

    A implementação pw_open é:

    $ grep -A 3 'int pw_open (int mode)' lib/pwio.c 
    int pw_open (int mode)
    {
        return commonio_open (&passwd_db, mode);
    }
    

    Chegando mais perto, mas ainda não chegamos lá. commonio_open é o nosso novo objetivo.

  7. Pesquise commonio_open :

    $ grep -R commonio_open *
    (...)
    lib/commonio.c:int commonio_open (struct commonio_db *db, int mode)
    
  8. Abra lib/commonio.c e role para a função commonio_open :

    int commonio_open (struct commonio_db *db, int mode)
    {
    (...)
    
        fd = open (db->filename,
                     (db->readonly ? O_RDONLY : O_RDWR)
                   | O_NOCTTY | O_NONBLOCK | O_NOFOLLOW);
    

    Você vê O_NOFOLLOW ? Este é o culpado (de man 2 open ):

    O_NOFOLLOW 
          If pathname is a symbolic link, then the open fails.
    

Resumindo, useradd.c usa pw_open , que por sua vez usa commonio_open , que abre /etc/passwd usando syscall open com a opção O_NOFOLLOW , que rejeita links simbólicos.

Embora um symlink possa ser usado como um substituto de um arquivo em muitas (eu diria a maioria) situações, useradd é bastante exigente e o rejeita, provavelmente porque um /etc/passwd com link simbólico sugere strongmente que /etc tem foi adulterado.

Por que devo deixar o passwd em /etc ?

Existem vários arquivos em /etc necessários para inicializar e fazer login, por exemplo (mas não limitados a): fstab , inittab , passwd , shadow e os scripts de inicialização em init.d/ . Qualquer sysadmin espera que esses arquivos estejam lá, não ligados simbolicamente a /home ou a qualquer lugar.

Então, mesmo que você pudesse, você deveria deixar passwd em /etc .

Além disso, a estrutura do sistema de arquivos no Linux é bem definida, dê uma olhada aqui: link . Há também um capítulo para /etc . Não é recomendável mudar as coisas.

    
por 25.03.2013 / 14:49
4

Doctor, it hurts when I do this.

Well, don't do it then!

Sério, não coloque os arquivos como críticos em um local inesperado. Tudo o que você está tentando testar: encontre uma maneira melhor. Se você está tentando fazer uma autenticação central: use o ldap. Ou nis se você precisar.

    
por 25.03.2013 / 10:22

Tags